Two Ways to Realize Android Side-Slide Menu

Two Realizations of Side Slide Menu

  1. Drawer Layout is more flexible.
  2. Using Drawer Layout + Navigation View, this is Google's standardization of Material Design.

Using Drawer Layout to realize sideslip

First, we need a layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#D197F2"
        app:title="Title"
        app:titleTextColor="#fff"/>

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="content"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="200dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@android:color/holo_blue_light"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Side Slide Menu 1"/>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Side Slide Menu 2"/>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Side Slide Menu 3"/>

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


The layout side-slip menu includes the menu section and the content section, wrapped in Drawer Layout. Among them, the root layout of the menu section needs to add android:layout_gravity="start", if it is right-sliding, it can be changed to end. In this way, a basic side slip effect can be achieved.

DrawerLayout is actually implemented through ViewDragHelper. The relevant code of DrawerLayout constructor is as follows:

public DrawerLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    mLeftCallback = new ViewDragCallback(Gravity.LEFT);
    mRightCallback = new ViewDragCallback(Gravity.RIGHT);

    mLeftDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mLeftCallback);
    mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
    mLeftDragger.setMinVelocity(minVel);
    mLeftCallback.setDragger(mLeftDragger);
}

Using Drawer Layout's monitoring to achieve some results

For example, when we can slide sideways, the button in the upper left corner of the Toolbar changes in real time. We can add a monitor to ActionBarDrawer Toggle:

toolbar = (Toolbar) findViewById(R.id.toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer);

ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
toggle.syncState();

drawer.addDrawerListener(toggle);

Now let's analyze the implementation principle:

Among them, ActionBarDrawerToggle implements DrawerLayout.DrawerListener. And constantly refresh the top left corner of the Drawerable during the sliding process:

@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
    setPosition(Math.min(1f, Math.max(0, slideOffset)));
}
The implementation of setPosition is as follows:

private void setPosition(float position) {
    if (position == 1f) {
        mSlider.setVerticalMirror(true);
    } else if (position == 0f) {
        mSlider.setVerticalMirror(false);
    }
    mSlider.setProgress(position);
}

In fact, the process of sliding is constantly changing the rogress of mSlider (a custom Drawerable object), thus constantly refreshing the state.

Therefore, we can do some custom effects, such as zooming and panning when sliding:

drawer.addDrawerListener(new DrawerLayout.DrawerListener() {

    @Override
    public void onDrawerStateChanged(int newState) {
        // Change of state

    }

    @Override
    public void onDrawerSlide(View drawerView, float slideOffset) {
        // Continuously callback slideOffset: 0~1 during the sliding process
        View content = drawer.getChildAt(0);
        float scale = 1 - slideOffset;//1~0
        float leftScale = (float) (1 - 0.3 * scale);
        float rightScale = (float) (0.7f + 0.3 * scale);//0.7~1
        drawerView.setScaleX(leftScale);//1~0.7
        drawerView.setScaleY(leftScale);//1~0.7

        content.setScaleX(rightScale);
        content.setScaleY(rightScale);
        content.setTranslationX(drawerView.getMeasuredWidth() * (1 - scale));//0~width

    }

    @Override
    public void onDrawerOpened(View drawerView) {
        // open
    }

    @Override
    public void onDrawerClosed(View drawerView) {
        // Close
    }
});

Using Drawer Layout+Navigation View to Realize Side Slip

Similarly, we need a layout. Similarly, we need to use Drawer Layout to wrap content and menus, where the menu is a Navigation View, which can specify the header and the menu section, and provide some settings for the properties. (As you can see, the flexibility of using Navigation View is poor. If the project uses this template directly, it can be used directly. Otherwise, we still use the general way to achieve it.)

<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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Content section -->
    <FrameLayout
        android:id="@+id/fl"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

    <!-- Menu section -->
    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/navigation_headerlayout"
        app:menu="@menu/navigation_menu"/>

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

Here we designate the head as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_marginTop="20dp"
        android:src="@drawable/icon_people"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="test"
        android:textSize="20sp"/>

</LinearLayout>

The menu section is as follows (created under the menu folder), where menus can be nested:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/action_gallery"
        android:icon="@android:drawable/ic_menu_gallery"
        android:orderInCategory="100"
        android:title="Album"
        />
    <item
        android:id="@+id/action_details"
        android:icon="@android:drawable/ic_menu_info_details"
        android:orderInCategory="100"
        android:title="details"
        />
    <item
        android:id="@+id/action_about"
        android:icon="@android:drawable/ic_menu_help"
        android:orderInCategory="100"
        android:title="about"
        />
    <item
        android:id="@+id/action_music"
        android:icon="@android:drawable/ic_menu_more"
        android:orderInCategory="100"
        android:title="Music"
        >
        <menu>
            <item
                android:id="@+id/action_play"
                android:icon="@android:drawable/ic_media_play"
                android:title="play"/>
            <item
                android:id="@+id/action_pause"
                android:icon="@android:drawable/ic_media_pause"
                android:title="Pause"/>
        </menu>
    </item>

</menu>

So far, you can achieve the sideslip, and finally we add the corresponding click event, and then close the menu:

nav_view = (NavigationView) findViewById(R.id.nav_view);
drawer = (DrawerLayout) findViewById(R.id.drawer);
nav_view.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        Toast.makeText(NavigationViewActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
        drawer.closeDrawer(nav_view);
        return false;
    }
});

nav_view.getHeaderView(0).findViewById(R.id.iv_icon).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(NavigationViewActivity.this, "Click on the head Icon", Toast.LENGTH_SHORT).show();
        drawer.closeDrawer(nav_view);
    }
});

Keywords: Android DrawerLayout encoding xml

Added by indian98476 on Sat, 22 Jun 2019 23:41:56 +0300