DrawerLayout是Android.support.v4.view包中定义的侧滑系统控件,在很多商业APP中都使用了侧滑控件,如下所示:
网易新闻客户端中的侧滑菜单
腾讯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>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
注意事项:
- 要使用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();
mDrawerList.setItemChecked(position, true);
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
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
要点总结:
- 创建Drawer布局文件;
- 初始化Drawer列表;
- 响应Drawer列表的点击事件。
效果演示
当从屏幕左侧边缘向右滑动时,有如下效果:
点击某一项,切换至相应fragment:
补充
为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被拉出时,ActionBar右上角的图标(如搜索图标)隐藏
当DrawerLayout被收起时,ActionBar右上角的图标显示
- 如上所示,为实现当DrawerLayout被拉出时,ActionBar右上角的图标(如搜索图标)隐藏;当DrawerLayout被收起时,ActionBar右上角的图标显示的效果,可在onDrawerOpened()和onDrawerClosed()方法中添加invalidateOptionMenu()方法,以重绘该图标,在执行该方法之前,系统会先调用onPrepareOptionsMenu(Menu menu)方法,可通过该方法设置DrawerLayout被拉出和隐藏时,ActionBar右上角图标的隐藏状态: