一、介绍
导航抽屉可以显示在屏幕的左右两侧,默认情况下是隐藏的,当用户用手指从边缘向另一侧滑动的时候,会在内容上方出现一个隐藏的面板,此时内容视图区域会变暗。当点击面板外部或者向原来的方向滑动的时候,导航抽屉就会消失。通常这个导航抽屉用来当作流行的侧滑菜单。
这个类就是DrawerLayout,该类位于V4包中。
android.support.v4.widget.DrawerLayout.
二、DrawerLayout的使用
直接将DrawerLayout作为根布局,然后其内部第一个View为内容区域,第二个View为左侧菜单,第三个View为右侧侧滑菜单,当前第三个是可选的。
第一个View的宽高应当设置为fill_parent。
第二、三个View需要设置android:layout_gravity="left",和android:layout_gravity="right";且一般高度设置为fill_parent,宽度为固定值,即侧滑菜单的宽度。
三、左侧菜单布局
使用列表视图ListView
reslayoutleft_menu.xml
<ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list" android:layout_width="match_parent" android:layout_height="wrap_content" android:entries="@array/color" android:paddingTop="5dp" android:layout_marginTop="80dp" > </ListView>
数组资源文件 resvaluesarrays.xml
<resources> <string-array name="color" style="@style/textColor"> <item>红</item> <item>橙</item> <item>黄</item> <item>绿</item> </string-array> </resources>
四、右侧菜单布局 简单的四个图标加文字 reslayoutright_menu.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_gravity="center_vertical" android:layout_marginBottom="20dp" android:orientation="vertical" > <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_gravity="center" android:src="@drawable/wode" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="扫一扫" android:textColor="#ffffff" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_gravity="center_vertical" android:layout_marginBottom="20dp" android:orientation="vertical" > <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_gravity="center" android:src="@drawable/saoma" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="讨论组" android:textColor="#ffffff" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_gravity="center_vertical" android:layout_marginBottom="20dp" android:orientation="vertical" > <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_gravity="center" android:src="@drawable/mobile" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="手机" android:textColor="#ffffff" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_gravity="center_vertical" android:layout_marginBottom="20dp" android:orientation="vertical" > <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_gravity="center" android:src="@drawable/dianhua" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="电话" android:textColor="#ffffff" /> </LinearLayout> </LinearLayout>
五、主布局
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/drawer" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- 内容视图 --> <RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/blue_sky" > <Button android:onClick="openRight" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:background="#80DDF4D4" android:text="右侧菜单" /> </RelativeLayout> <!-- 左侧菜单 这里使用fragment --> <fragment android:name="com.example.drawerlayouttest.LeftMenuFragment" android:layout_width="100dp" android:layout_height="fill_parent" android:layout_gravity="left" android:tag="left"/> <!-- 右侧菜单 --> <fragment android:name="com.example.drawerlayouttest.RightMenuFragment" android:layout_width="80dp" android:layout_height="fill_parent" android:layout_gravity="right" android:tag="right"/> </android.support.v4.widget.DrawerLayout>
六、Fragment实现,加载菜单布局
public class LeftMenuFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.left_menu, container, false); } } public class RightMenuFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.right_menu, container, false); } }
七、MainActivity类实现
public class MainActivity extends FragmentActivity { private DrawerLayout mDrawer; private View mLeft; private ListView list; private float mFirstX = 0; // 手指按下时的x坐标 private int mSensity = 30; // 菜单打开关闭的手势范围 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); list = (ListView) findViewById(R.id.list); list.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mDrawer.closeDrawer(Gravity.START); String text = parent.getItemAtPosition(position).toString(); Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show(); } }); mDrawer = (DrawerLayout) findViewById(R.id.drawer); mLeft = mDrawer.getChildAt(1); initEvent(); } private void initEvent() { mDrawer.setDrawerListener(new DrawerListener() { /** * 当抽屉滑动状态改变的时候被调用 * 状态值是STATE_IDLE(闲置--0), STATE_DRAGGING(拖拽的--1), STATE_SETTLING(固定--2)中之一。 * 抽屉打开的时候,点击抽屉,drawer的状态就会变成STATE_DRAGGING,然后变成STATE_IDLE */ @Override public void onDrawerStateChanged(int arg0) { Log.i("drawer", "drawer的状态:" + arg0); } // 菜单滑动 @Override public void onDrawerSlide(View arg0, float rate) { // rate从0.0 ~ 1.0 菜单的显示率 // 可以设置菜单出现的效果 缩放、透明度变化 参考HorizontalScroll实现的菜单缩放 } /** * 当一个抽屉被完全打开的时候被调用 */ @Override public void onDrawerOpened(View arg0) { Log.i("drawer", "抽屉被完全打开了!"); }<span style="font-family: Arial, Helvetica, sans-serif;"> </span> <span style="font-family: Arial, Helvetica, sans-serif;"> </span> /** * 当一个抽屉完全关闭的时候调用此方法 */ @Override public void onDrawerClosed(View arg0) { Log.i("drawer", "抽屉被完全关闭了!"); } }); } /** * DrawerLayout只支持边缘滑动打开菜单 * 通过判断手势滑动的距离来增加打开菜单的手势范围 在屏幕范围内滑动均可打开关闭菜单 */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mFirstX = ev.getX(); break; case MotionEvent.ACTION_MOVE: float curX = ev.getX(); // 向右滑动 预期效果:关闭右侧菜单 或 打开左侧菜单 if(curX-mFirstX > mSensity){ // 如果右侧菜单打开则关闭 // 从左到右的阅读顺序中 left相当于start , right 相当于 end if(mDrawer.isDrawerOpen(Gravity.END)){ mDrawer.closeDrawer(Gravity.END); // 关闭右侧菜单后 允许 左侧菜单滑动出现 mDrawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.START); }else{ mDrawer.openDrawer(Gravity.START); // 关闭右侧菜单滑动出现 mDrawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.END); } } // 向左滑动 else if(mFirstX-curX > mSensity){ // 如果左侧菜单打开则关闭 if(mDrawer.isDrawerOpen(Gravity.LEFT)){ mDrawer.closeDrawer(Gravity.LEFT); // 关闭左侧菜单后 允许 右侧菜单滑动出现 mDrawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.RIGHT); }else{ mDrawer.openDrawer(Gravity.RIGHT); // 右侧菜单打开后 关闭 左侧菜单滑动出现 mDrawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.LEFT); } } default: break; } return super.dispatchTouchEvent(ev); } public void openRight(View view) { mDrawer.openDrawer(Gravity.RIGHT);// 展开侧边的菜单 } }
八、项目运行图
项目下载地址