­

Android开发(37) 使用DrawerLayout实现抽屉式导航菜单

  • 2020 年 3 月 16 日
  • 筆記

概述

最近流行 左侧抽屉式的导航条菜单,知乎,360,QQ都使用了这样的导航菜单,我们也了解下:

Android Design 的流行趋势:Navigation Drawer 导航抽屉 参考这篇文章:http://www.geekpark.net/topics/183724

效果图:

特点

1.标题栏(或者actionBar) 做的有个 菜单图标按钮(三条线或者其他)。一般这样的标题栏左侧和右侧都会有图标按钮。如图1所示。

2.点击图标按钮 从左侧向右 慢慢退出一个 菜单视图(View),遮盖在 内容页(首页)的视图上,同时,产生遮盖层。如图2所示。

官方示例

参考自谷歌开发者网站的示例,在这个页面可以下载到示例。http://developer.android.com/training/implementing-navigation/nav-drawer.html

引用类库

需要android-support-v4.jar

主要控件

谷歌提供的抽屉控件: android.support.v4.widget.DrawerLayout

参考这片文章的解释:http://blog.csdn.net/xiahao86/article/details/8995827

具体实现

首页(比如叫:MainActivity)内容布局,写一个 android.support.v4.widget.DrawerLayout,它需要包含两个内容视图元素,第一个视图元素是 主显示内容页,第二个是要抽屉弹出的视图。

<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" >        <!--           As the main content view, the view below consumes the entire           space available using match_parent in both dimensions.      -->        <FrameLayout          android:id="@+id/content_frame"          android:layout_width="match_parent"          android:layout_height="match_parent" />        <!--           android:layout_gravity="start" tells DrawerLayout to treat           this as a sliding drawer on the left side for left-to-right           languages and on the right side for right-to-left languages.           The drawer is given a fixed width in dp and extends the full height of           the container. A solid background is used for contrast           with the content view.      -->        <zyf.demo.navigationdrawer.NavigationMenu          android:id="@+id/navigation_menu"          android:layout_width="240dp"          android:layout_height="match_parent"          android:layout_gravity="start" >      </zyf.demo.navigationdrawer.NavigationMenu>    </android.support.v4.widget.DrawerLayout>

我在这里写了个自定义控件 “ zyf.demo.navigationdrawer.NavigationMenu " , 注意它的 android:layout_gravity="start" ,是 start 不是left。

MainActivity需要 为DrawerLayout 注册一个回调事件接口ActionBarDrawerToggle ,这个事件的实现者监听器会获得 抽屉弹出(onDrawerOpened)和关闭(onDrawerClosed)的事件。

MainActivity 的代码

package zyf.demo.navigationdrawer;    import android.os.Bundle;  import android.app.Activity;  import android.app.Fragment;  import android.app.FragmentManager;  import android.content.res.Configuration;  import android.graphics.drawable.ColorDrawable;  import android.support.v4.app.ActionBarDrawerToggle;  import android.support.v4.widget.DrawerLayout;  import android.view.Menu;  import android.view.MenuInflater;  import android.view.MenuItem;  import android.view.View;  import android.widget.Toast;    public class MainActivity extends Activity {      private NavigationMenu mNavigationMenu;      private DrawerLayout mDrawerLayout;      private ActionBarDrawerToggle mDrawerToggle;        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);            // 获得抽屉控件          mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);          // 获得菜单控件          mNavigationMenu = (NavigationMenu) findViewById(R.id.navigation_menu);          mNavigationMenu.attacthDrawer(mDrawerLayout);            // enable ActionBar app icon to behave as action to toggle nav          // drawer          getActionBar().setDisplayHomeAsUpEnabled(true);          // 使actionbar 的logo图标透明不可见          getActionBar().setIcon(                  new ColorDrawable(getResources().getColor(                          android.R.color.transparent)));            // 注册导航菜单抽屉 的弹出和关闭事件          mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */          mDrawerLayout, /* DrawerLayout object */          R.drawable.ic_notification_content, /*                                               * nav drawer image to replace 'Up'                                               * caret                                               */          R.string.drawer_open, /* "open drawer" description for accessibility */          R.string.drawer_close /* "close drawer" description for accessibility */          ) {              // 当导航菜单抽屉 关闭后              public void onDrawerClosed(View view) {                  // 显示当前内容页的标题                  getActionBar().setTitle(getTitle());                  invalidateOptionsMenu(); // creates call to                                              // onPrepareOptionsMenu()              }                // 当导航菜单抽屉 打开后              public void onDrawerOpened(View drawerView) {                  // 显示导航菜单的标题                  getActionBar().setTitle(mNavigationMenu.getTitle());                  invalidateOptionsMenu(); // creates call to                                              // onPrepareOptionsMenu()              }          };          mDrawerLayout.setDrawerListener(mDrawerToggle);            // 显示首页的内容          showFragment(new HomeFragment());            // 当更换主页内的 子页面(fragment)时,隐藏导航菜单          mNavigationMenu.hide();      }        @Override      public boolean onCreateOptionsMenu(Menu menu) {          MenuInflater inflater = getMenuInflater();          inflater.inflate(R.menu.main, menu);          return super.onCreateOptionsMenu(menu);      }        /* Called whenever we call invalidateOptionsMenu() */      @Override      public boolean onPrepareOptionsMenu(Menu menu) {          // If the nav drawer is open, hide action items related to the content          // view          // 当弹出导航菜单时,使 actionbar的扩展按钮不可见          boolean drawerOpen = mDrawerLayout.isDrawerOpen(mNavigationMenu);          menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);          return super.onPrepareOptionsMenu(menu);      }        @Override      public boolean onOptionsItemSelected(MenuItem item) {          // The action bar home/up action should open or close the drawer.          // ActionBarDrawerToggle will take care of this.          if (mDrawerToggle.onOptionsItemSelected(item)) {              return true;          }          // Handle action buttons          switch (item.getItemId()) {          case R.id.action_websearch:              Toast.makeText(this, "你点击了搜索按钮", Toast.LENGTH_LONG).show();              return true;          default:              return super.onOptionsItemSelected(item);          }      }        private void showFragment(Fragment fragment) {          FragmentManager fragmentManager = getFragmentManager();          fragmentManager.beginTransaction()                  .replace(R.id.content_frame, fragment).commit();      }        @Override      protected void onPostCreate(Bundle savedInstanceState) {          super.onPostCreate(savedInstanceState);          // Sync the toggle state after onRestoreInstanceState has occurred.          mDrawerToggle.syncState();      }        @Override      public void onConfigurationChanged(Configuration newConfig) {          super.onConfigurationChanged(newConfig);          // Pass any configuration change to the drawer toggls          mDrawerToggle.onConfigurationChanged(newConfig);      }    }

下面给出我写的自定义控件的实现:

<?xml version="1.0" encoding="utf-8"?>  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="match_parent" >     <ListView          android:id="@+id/listView1"          android:layout_width="240dp"          android:layout_height="match_parent"          android:layout_gravity="start"          android:choiceMode="singleChoice"            android:background="#FFFFFF"/>  </RelativeLayout>

代码 package zyf.demo.navigationdrawer;

import android.content.Context;  import android.support.v4.widget.DrawerLayout;  import android.util.AttributeSet;  import android.view.LayoutInflater;  import android.view.View;  import android.widget.AdapterView;  import android.widget.ArrayAdapter;  import android.widget.ListView;  import android.widget.RelativeLayout;  import android.widget.Toast;    public class NavigationMenu extends RelativeLayout {      LayoutInflater mLayoutInflater;      ListView mlistView1;      String[] menuItemsDataSource;      private DrawerLayout mDrawerLayout;// 关联到的抽屉控件        public NavigationMenu(Context context, AttributeSet attrs, int defStyle) {          super(context, attrs, defStyle);          initLayout(context);      }        public NavigationMenu(Context context, AttributeSet attrs) {          super(context, attrs);          initLayout(context);      }        public NavigationMenu(Context context) {          super(context);          initLayout(context);      }        private void initLayout(Context context) {          mLayoutInflater = LayoutInflater.from(context);          View contentView = mLayoutInflater.inflate(R.layout.navigation_menu,                  null);          RelativeLayout.LayoutParams lp = new LayoutParams(                  LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);          this.addView(contentView, lp);            mlistView1 = (ListView) contentView.findViewById(R.id.listView1);          menuItemsDataSource = getResources().getStringArray(                  R.array.navigation_menu_items_array);            mlistView1.setAdapter(new ArrayAdapter<String>(context,                  R.layout.navaigation_menu_list_view_item, menuItemsDataSource));          mlistView1.setOnItemClickListener(new DrawerItemClickListener());      }        /**       * 包含 的 listView的点击事件       * @author yunfei       *       */      private class DrawerItemClickListener implements              ListView.OnItemClickListener {          @Override          public void onItemClick(AdapterView<?> parent, View view, int position,                  long id) {              // selectItem(position);                mlistView1.setItemChecked(position, true);              hide();                Toast.makeText(getContext(), "你选择了" + position, 0).show();          }      }          public CharSequence getTitle() {          return "导航菜单";      }        /**       * 关联到 drawerLayout       * @param drawerLayout       */      public void attacthDrawer(DrawerLayout drawerLayout) {          mDrawerLayout = drawerLayout;      }        /**       * 隐藏       */      public void hide() {          if (mDrawerLayout != null)              mDrawerLayout.closeDrawer(NavigationMenu.this);      }        /**       * 出现       */      public void show() {          if (mDrawerLayout != null)              mDrawerLayout.openDrawer(NavigationMenu.this);      }      }

代码下载:

http://yunpan.cn/cggiDkFNCp2Jw 访问密码 c3ed

参考:

http://blog.csdn.net/xiahao86/article/details/8995827 http://developer.android.com/training/implementing-navigation/nav-drawer.html http://www.geekpark.net/topics/183724