侧滑控件DrawerLayout浅析

DrawerLayout是android.support.v4.view包中定义的侧滑系统控件,在很多商业APP中都使用了侧滑控件,如下所示:

侧滑控件DrawerLayout浅析_第1张图片
网易新闻客户端中的侧滑菜单

侧滑控件DrawerLayout浅析_第2张图片
腾讯QQ客户端中的侧滑菜单

本文将浅析一个利用DrawerLayout实现侧滑功能的简易菜单,点击侧滑菜单中的每一项,将切换Activity中的Fragment。

activity的XML布局

主Activity的XML布局代码如下:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#111"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp" />

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

注意事项:

  • 要使用DrawerLayout的全限定包名:android.support.v4.widget.DrawerLayout;
  • 主视图内容(上述代码为FrameLayout)必须是DrawerLayout的第一个子控件;
  • 侧滑视图(上述代码为ListView)需指定属性android:layout_gravity,属性值”start”代表抽屉菜单隐藏在屏幕左侧,从左向右可滑出;属性值”end”反之。属性值”left”和”right”同样可实现相应效果,但Google官方不推荐使用;
  • 侧滑视图的的宽度(用属性android:layout_width指定)尽量不要超过320dp,以保证看到一些主视图内容;

侧滑菜单ListView的XML布局

代码如下:

<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:attr/activatedBackgroundIndicator" android:gravity="center_vertical" android:minHeight="?android:attr/listPreferredItemHeightSmall" android:paddingLeft="16dp" android:paddingRight="16dp" android:textAppearance="?android:attr/textAppearanceListItemSmall" android:textColor="#fff" />

定义Fragment的布局XML

为Fragment定义布局代码如下:

<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/textview" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textSize="50sp"/>

Activity逻辑实现

public class MainActivity extends Activity {
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private String[] mItemArray;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);
        mItemArray = getResources().getStringArray(R.array.item_array);

        mDrawerList.setAdapter(new ArrayAdapter<String>(this,
                R.layout.drawer_list_item, mItemArray));

        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
    }

    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView parent, View view, int position, long id) {
            selectItem(position);
        }
    }

    private void selectItem(int position) {
        Fragment fragment = new MyFragment();
        Bundle args = new Bundle();
        args.putInt(MyFragment.ITEM_NUMBER, position);
        fragment.setArguments(args);

        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.content_frame, fragment)
                .commit();
        //点击ListView中的项时给用户以反馈
        mDrawerList.setItemChecked(position, true);
        //打开主内容视图的同时,收起滑动菜单DrawerLayout
        mDrawerLayout.closeDrawer(mDrawerList);
    }

    public static class MyFragment extends Fragment {
        public static final String ITEM_NUMBER = "item_number";

        public MyFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_item, container, false);
            int i = getArguments().getInt(ITEM_NUMBER);
            String itemName = getResources().getStringArray(R.array.item_array)[i];
            ((TextView) (rootView.findViewById(R.id.textview))).setText(itemName);
            return rootView;
        }
    }
}

要点总结:

  1. 创建Drawer布局文件;
  2. 初始化Drawer列表;
  3. 响应Drawer列表的点击事件。

效果演示

当从屏幕左侧边缘向右滑动时,有如下效果:

点击某一项,切换至相应fragment:

侧滑控件DrawerLayout浅析_第3张图片侧滑控件DrawerLayout浅析_第4张图片

补充

为DrawerLayout添加监听事件的注意事项:

  • mDrawerLayout.setDrawerListener(DrawerLayout.DrawerListener);

为DrawerLayout绑定监听器,并传入DrawerLayout的内部接口对象DrawerListener,可以监听当DrawerLayout处于滑入滑出状态时,触发动作事件。

  • ActionBarDrawerToggle是DrawerLayout.DrawerListener的具体实现类:
    –修改ActionBar的默认图标(通过其构造方法改变android.R.id.home图标);
    –DrawerLayout被拉出、隐藏时,通过该类添加动画效果 (syncState()方法);
    –重写ActionBarDrawerToggle的onDrawerOpened()和onDrawerClosed()方法,以监听DrawerLayout被拉出和隐藏时的动作事件;
  • 重写Activity的onPostCreate()和 onConfigurationChanged()方法,以配合syncState()方法实现ActionBar上图标的动画效果。

侧滑控件DrawerLayout浅析_第5张图片


当DrawerLayout被拉出时,ActionBar右上角的图标(如搜索图标)隐藏

这里写图片描述
当DrawerLayout被收起时,ActionBar右上角的图标显示

  • 如上所示,为实现当DrawerLayout被拉出时,ActionBar右上角的图标(如搜索图标)隐藏;当DrawerLayout被收起时,ActionBar右上角的图标显示的效果,可在onDrawerOpened()和onDrawerClosed()方法中添加invalidateOptionMenu()方法,以重绘该图标,在执行该方法之前,系统会先调用onPrepareOptionsMenu(Menu menu)方法,可通过该方法设置DrawerLayout被拉出和隐藏时,ActionBar右上角图标的隐藏状态:

你可能感兴趣的:(Drawer,侧滑菜单)