Đó là chưa rõ chính xác mà bạn muốn thực hiện giao diện người dùng ngăn kéo của bạn, vì vậy giải pháp sau đây là khá chung chung, ở chỗ nó sẽ làm việc với NavigationView
s, RecyclerView
s, hoặc khá nhiều bất cứ loại trong số View
bạn muốn.
Giải pháp này sử dụng một tùy chỉnh ViewSwitcher
lớp con có tác dụng như ngăn kéo bên trái một DrawerLayout
's, và giữ hai con View
s, một là ngăn kéo chính View
, và người kia là ngăn kéo thứ hai mở ra trên nó.
Lớp DoubleDrawerView
là ViewSwitcher
tương đối đơn giản tải Animation
s của riêng nó và tranh luận chúng một cách thích hợp để tạo hiệu ứng của ngăn mở thứ hai và đóng trên ngăn đầu tiên. Nó theo dõi trạng thái của nó để nó có thể được phục hồi một cách chính xác sau một vòng xoay thiết bị vv
public class DoubleDrawerView extends ViewSwitcher {
private static final int NONE = -1;
private static final int MAIN_VIEW_INDEX = 0;
private static final int DRAWER_VIEW_INDEX = 1;
private Animation slideInAnimation, slideOutAnimation, noAnimation;
private boolean animating = false;
private Animation.AnimationListener listener = new Animation.AnimationListener() {
@Override
public void onAnimationEnd(Animation anim) {
animating = false;
}
@Override
public void onAnimationStart(Animation anim) {}
@Override
public void onAnimationRepeat(Animation anim) {}
};
public DoubleDrawerView(Context context) {
this(context, null);
}
public DoubleDrawerView(Context context, AttributeSet attrs) {
super(context, attrs);
slideInAnimation = AnimationUtils.loadAnimation(context, R.anim.slide_in_left);
slideOutAnimation = AnimationUtils.loadAnimation(context, R.anim.slide_out_left);
noAnimation = AnimationUtils.loadAnimation(context, R.anim.none);
noAnimation.setAnimationListener(listener);
}
public void openInnerDrawer() {
if (getDisplayedChild() != DRAWER_VIEW_INDEX) {
setChildAndAnimate(DRAWER_VIEW_INDEX, true);
}
}
public void closeInnerDrawer() {
if (getDisplayedChild() != MAIN_VIEW_INDEX) {
setChildAndAnimate(MAIN_VIEW_INDEX, true);
}
}
public boolean isInnerDrawerOpen() {
return getDisplayedChild() == DRAWER_VIEW_INDEX;
}
private void setChildAndAnimate(int whichChild, boolean doAnimate) {
if (doAnimate) {
setAnimationForChild(whichChild);
}
else {
setAnimationForChild(NONE);
}
animating = doAnimate;
setDisplayedChild(whichChild);
}
private void setAnimationForChild(int whichChild) {
if (whichChild == DRAWER_VIEW_INDEX) {
setInAnimation(slideInAnimation);
setOutAnimation(noAnimation);
}
else if (whichChild == MAIN_VIEW_INDEX) {
setInAnimation(noAnimation);
setOutAnimation(slideOutAnimation);
}
else {
setInAnimation(null);
setOutAnimation(null);
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (animating) {
return true;
}
else {
return super.onInterceptTouchEvent(ev);
}
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.whichChild = getDisplayedChild();
return ss;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setChildAndAnimate(ss.whichChild, false);
}
private static class SavedState extends BaseSavedState {
int whichChild;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
whichChild = in.readInt();
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(whichChild);
}
public static final Parcelable.Creator<SavedState>
CREATOR = new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
DoubleDrawerView
sử dụng các tập tin XML sau cho Animation
s của nó. Những thư mục này phải nằm trong thư mục res/anim/
của dự án của bạn.
slide_in_left.xml
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="-100%p" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
slide_out_left.xml
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0" android:toXDelta="-100%p"
android:duration="@android:integer/config_mediumAnimTime"/>
none.xml
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
bố trí của ví dụ này là một tiêu chuẩn DrawerLayout
với một DoubleDrawerView
cho ngăn kéo của mình, và hai đơn giản 0.123.s trong đó. Lưu ý rằng ngăn kéo chính View
phải được liệt kê trước tiên bên trong DoubleDrawerView
, với ngăn thứ hai, bên trong ngăn View
sau.
activity_main.xml
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.example.doubledrawer.DoubleDrawerView
android:id="@+id/double_drawer_view"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left">
<android.support.design.widget.NavigationView
android:id="@+id/main_navigation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:menu="@menu/navigation_main" />
<android.support.design.widget.NavigationView
android:id="@+id/settings_navigation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:menu="@menu/navigation_settings" />
</com.example.doubledrawer.DoubleDrawerView>
</android.support.v4.widget.DrawerLayout>
Vì lợi ích của một vết cắt đầy đủ và dán dụ, một số res/menu/
file đơn giản cho NavigationView
s trên.
navigation_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group
android:id="@+id/group_screens"
android:checkableBehavior="single">
<item
android:id="@+id/menu_screen_1"
android:title="Screen 1" />
<item
android:id="@+id/menu_screen_2"
android:title="Screen 2"/>
</group>
<item
android:id="@+id/menu_open_settings"
android:title="Open Settings" />
</menu>
navigation_settings.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_close_settings"
android:title="Back to Main" />
<group
android:id="@+id/group_settings">
<item
android:id="@+id/menu_setting_1"
android:title="Setting 1" />
<item
android:id="@+id/menu_setting_2"
android:title="Setting 2" />
</group>
</menu>
Trong ví dụ Activity
, chúng tôi chỉ nhận được tham chiếu đến DoubleDrawerView
và NavigationView
s, và thực hiện một OnNavigationItemSelectedListener
để mở và đóng ngăn kéo bên trong cho phù hợp.
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private DrawerLayout drawerLayout;
private DoubleDrawerView doubleDrawerView;
private NavigationView mainNavigationView, settingsNavigationView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
doubleDrawerView = (DoubleDrawerView) findViewById(R.id.double_drawer_view);
mainNavigationView = (NavigationView) findViewById(R.id.main_navigation_view);
settingsNavigationView = (NavigationView) findViewById(R.id.settings_navigation_view);
mainNavigationView.setNavigationItemSelectedListener(this);
settingsNavigationView.setNavigationItemSelectedListener(this);
drawerLayout.openDrawer(Gravity.LEFT);
}
@Override
public boolean onNavigationItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_open_settings:
doubleDrawerView.openInnerDrawer();
break;
case R.id.menu_close_settings:
doubleDrawerView.closeInnerDrawer();
break;
// Additional cases as needed
// This example simply Toasts the title for the extra sample items
default:
Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT).show();
}
return true;
}
}
Điều này có thể, nhưng không phải với tệp xml menu chuẩn. Bạn phải thực hiện một hack nhỏ bằng cách thêm bố cục tùy chỉnh vào 'NavigationView'. –
Bạn có quan tâm đến cách mở ngăn kéo thứ hai trong lần đầu tiên không? Ý tôi là, bạn cũng hỏi cách tạo kiểu cho những vật phẩm cụ thể đó hay bạn chỉ muốn chức năng ngăn kéo đôi? –
Tôi muốn nhấp vào cài đặt trong menu đầu tiên và menu phụ của cài đặt sẽ hoạt ảnh trên đầu tiên. Điều này được lấy từ ứng dụng amazon mà tôi đã cố gắng để lặp lại trong của riêng tôi. – ant2009