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

时间:2016-08-18 04:12:19

标签: android drawerlayout navigationview

Android Studio 2.1.3

我有这个设计我想跟随。

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

enter image description here

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

enter image description here

用户可以点击箭头Main Menu返回第一个。

这可能吗?

非常感谢任何建议

2 个答案:

答案 0 :(得分:6)

目前还不清楚您希望如何实现抽屉UI,因此以下解决方案非常通用,因为它应该适用于NavigationView s,RecyclerView或几乎任何类型的{ {1}}你想要的。

此解决方案使用自定义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<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } } 使用以下XML文件作为其DoubleDrawerView。这些应该在项目的Animation文件夹中。

res/anim/

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" /> ,其抽屉有DrawerLayout,其中有两个简单的DoubleDrawerView。请注意,主抽屉NavigationView必须首先列在View内,第二个内抽屉DoubleDrawerView后面。{/ p>

View

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> 的一些简单的res/menu/文件。

NavigationView

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> 中,我们只是引用了ActivityDoubleDrawerView,并实现NavigationView来相应地打开和关闭内部抽屉。

OnNavigationItemSelectedListener

答案 1 :(得分:4)

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

Activity的布局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" />

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/inner_drawer_layout"
        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="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="left"
            app:menu="@menu/navigation_settings" />

    </android.support.v4.widget.DrawerLayout>

</android.support.v4.widget.DrawerLayout>

上面的示例NavigationView使用与my other answer here中显示的相同的菜单文件。

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