打开第二个抽屉布局作为第一个抽屉布局

Android Studio 2.1.3 

我有这个设计我想跟随。

在第一个抽屉布局上,我有一个设置选项。

在此处输入图像描述

当用户点击时,它将打开第二个抽象布局,如下所示。

在此处输入图像描述

用户可以通过单击箭头Main Menu返回到第一个。

这可能吗?

非常感谢任何建议

目前还不清楚您希望如何实现抽屉UI,因此以下解决方案非常通用,因为它可以与NavigationViewRecyclerView或几乎任何types的View

此解决方案使用自定义ViewSwitcher子类作为DrawerLayout的左抽屉,并保存两个子View ,一个是主抽屉View ,另一个是在其上打开的第二个抽屉。

DoubleDrawerView类是一个相对简单的ViewSwitcher ,可以加载自己的Animation ,并适当地调整它们,以便在第一个抽屉打开和关闭时产生效果。 它跟踪自己的状态,以便在设备旋转后可以正确恢复等。

 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 CREATOR = new Parcelable.Creator() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } } 

DoubleDrawerView使用以下XML文件作为其Animation 。 这些应该在您项目的res/anim/文件夹中。

slide_in_left.xml

  

slide_out_left.xml

  

none.xml

  

这个例子的布局是一个标准的DoubleDrawerView ,它的抽屉有一个DoubleDrawerView ,其中有两个简单的NavigationView 。 请注意,主抽屉View必须首先列在DoubleDrawerView ,第二个内部抽屉View后。

activity_main.xml

        

为了完整的剪切和粘贴示例,上面的NavigationView的一些简单的res/menu/文件。

navigation_main.xml

        

navigation_settings.xml

        

在示例Activity ,我们只获取对DoubleDrawerViewNavigationView的引用,并实现OnNavigationItemSelectedListenerOnNavigationItemSelectedListener地打开和关闭内部抽屉。

 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; } } 

此解决方案使用两个DrawerLayout ,一个嵌套在另一个中,代替自定义View 。 这可能稍微容易实现,但它需要在Activity本身中使用更专业的代码,因此它将更紧密地耦合到它所使用的任何类。

Activity的布局, activity_main.xml

        

上面的示例NavigationView使用相同的菜单文件,如我在其他答案中所示。

Activity ,我们获得了对DrawerLayout的引用,并在启动时在内部设置了稀松布颜色和锁定模式。 我们还需要自己处理后退按钮,因为添加第二个DrawerLayout第一个处理它。 在打开和关闭内部抽屉时,我们需要适当地设置锁定模式,以防止拖动内部抽屉。

 public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { private DrawerLayout drawerLayout, innerDrawerLayout; 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); innerDrawerLayout = (DrawerLayout) findViewById(R.id.inner_drawer_layout); mainNavigationView = (NavigationView) findViewById(R.id.main_navigation_view); settingsNavigationView = (NavigationView) findViewById(R.id.settings_navigation_view); mainNavigationView.setNavigationItemSelectedListener(this); settingsNavigationView.setNavigationItemSelectedListener(this); innerDrawerLayout.setScrimColor(Color.TRANSPARENT); innerDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); drawerLayout.openDrawer(Gravity.LEFT); } @Override public void onBackPressed() { if (drawerLayout.isDrawerOpen(Gravity.LEFT)) { drawerLayout.closeDrawer(Gravity.LEFT); } else { super.onBackPressed(); } } private void openInnerDrawer() { innerDrawerLayout.openDrawer(Gravity.LEFT); innerDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN); } private void closeInnerDrawer() { innerDrawerLayout.closeDrawer(Gravity.LEFT); innerDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); } @Override public boolean onNavigationItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_open_settings: openInnerDrawer(); break; case R.id.menu_close_settings: 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; } }