在support.v4包中新增的DrawerLayout可以满足基本的导航抽屉视图的需求,但是和网易等客户端相比还是有差距的
效果:
点击左边listview的栏目会切换背景,有2种方法调出左边的listview,一种是用手势从左向右滑动,一种是点击左上角的抽屉图片。
下面说下实现,是根据官网training给出的例子简化的。实现这个效果需要一点点Fragment和ActionBar的知识
第一步,.在布局文件中使用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">
- <!-- The main content view -->
- <FrameLayout
- android:id="@+id/content_frame"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- <!-- The navigation drawer -->
- <ListView android:id="@+id/left_drawer"
- android:layout_width="240dp"
- android:layout_height="match_parent"
- android:layout_gravity="start"
- android:choiceMode="singleChoice"
- android:divider="@android:color/transparent"
- android:dividerHeight="0dp"
- android:background="#111"/>
- </android.support.v4.widget.DrawerLayout>
要注意这几个原则:
1.主view(
content view) 必须是drawerlayout的第一个子节点
2.主view宽和高必需match_parent
3.
drawer view必须指定
android:layout_gravity
属性,如果值为“start”,会根据系统的语言顺序自动决定从左滑还是从右滑
4.
drawer view宽度不能太宽,最好不要超过320dp
这里主view是一个FrameLayout,用来切换Fragment,也就是显示的背景图片
第二步,初始化选择list
这里用最基本的adapter就可以
- mPlanetTitles = getResources().getStringArray(R.array.planets_array);
- mDrawerList = (ListView) findViewById(R.id.left_drawer);
- mDrawerList.setAdapter(new ArrayAdapter<String>(this,
- R.layout.drawer_list_item, mPlanetTitles));
第三步,处理列表的点击,这里用DrawerItemClickListener,onItemClick方法中处理fragment的切换
- private class DrawerItemClickListener implements ListView.OnItemClickListener {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- selectItem(position);
- }
- }
- mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
如果activitiy中有ActionBar的话,可以用ActionBarDrawerToggle
- mDrawerToggle = new ActionBarDrawerToggle(
- this, /* host Activity */
- mDrawerLayout, /* DrawerLayout object */
- R.drawable.ic_drawer, /* 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(mTitle);
- invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
- }
- public void onDrawerOpened(View drawerView) {
- getActionBar().setTitle(mDrawerTitle);
- invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
- }
- };
- mDrawerLayout.setDrawerListener(mDrawerToggle);
注意一定要设置这2个属性
- getActionBar().setDisplayHomeAsUpEnabled(true);
- getActionBar().setHomeButtonEnabled(true);
同时重写onOptionsItemSelected方法
- @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;
- }
- return false;
- }
下面是完整的代码:
工程目录:
、
布局文件:
activity_main.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:choiceMode="singleChoice"
- android:divider="@android:color/transparent"
- android:dividerHeight="0dp"
- android:background="#111"/>
- </android.support.v4.widget.DrawerLayout>
drawer_list_item.xml
- <?xml version="1.0" encoding="utf-8"?>
- <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:textAppearance="?android:attr/textAppearanceListItemSmall"
- android:gravity="center_vertical"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
- android:textColor="#fff"
- android:background="?android:attr/activatedBackgroundIndicator"
- android:minHeight="?android:attr/listPreferredItemHeightSmall"/>
fragment_planet.xml
- <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/image"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#000000"
- android:gravity="center"
- android:padding="32dp" />
资源文件 strings.xml,每个item的值和drawable文件夹下的图片名字一样
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <string name="app_name">Navigation Drawer Example</string>
- <string-array name="planets_array">
- <item>Mercury</item>
- <item>Venus</item>
- <item>Earth</item>
- <item>Mars</item>
- <item>Jupiter</item>
- <item>Saturn</item>
- <item>Uranus</item>
- <item>Neptune</item>
- </string-array>
- <string name="drawer_open">Open navigation drawer</string>
- <string name="drawer_close">Close navigation drawer</string>
- <string name="action_websearch">Web search</string>
- <string name="app_not_available">Sorry, there\'s no web browser available</string>
- </resources>
MainActivity.java
- public class MainActivity extends Activity {
- private DrawerLayout mDrawerLayout;
- private ListView mDrawerList;
- private ActionBarDrawerToggle mDrawerToggle;
- private CharSequence mDrawerTitle;
- private CharSequence mTitle;
- private String[] mPlanetTitles;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mTitle = mDrawerTitle = getTitle();
- mPlanetTitles = getResources().getStringArray(R.array.planets_array);
- mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
- mDrawerList = (ListView) findViewById(R.id.left_drawer);
- mDrawerList.setAdapter(new ArrayAdapter<String>(this,
- R.layout.drawer_list_item, mPlanetTitles));
- mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
- //使得左上角的图标可以控制drawerlayout
- getActionBar().setDisplayHomeAsUpEnabled(true);
- getActionBar().setHomeButtonEnabled(true);
- // ActionBarDrawerToggle ties together the the proper interactions
- // between the sliding drawer and the action bar app icon
- mDrawerToggle = new ActionBarDrawerToggle(
- this, /* host Activity */
- mDrawerLayout, /* DrawerLayout object */
- R.drawable.ic_drawer, /* 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(mTitle);
- invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
- }
- public void onDrawerOpened(View drawerView) {
- getActionBar().setTitle(mDrawerTitle);
- invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
- }
- };
- mDrawerLayout.setDrawerListener(mDrawerToggle);
- if (savedInstanceState == null) {
- selectItem(0);
- }
- }
- @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;
- }
- return false;
- }
- /* The click listner for ListView in the navigation drawer */
- 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) {
- // update the main content by replacing fragments
- Fragment fragment = new PlanetFragment();
- Bundle args = new Bundle();
- args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
- fragment.setArguments(args);
- FragmentManager fragmentManager = getFragmentManager();
- fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
- // update selected item and title, then close the drawer
- mDrawerList.setItemChecked(position, true);
- setTitle(mPlanetTitles[position]);
- mDrawerLayout.closeDrawer(mDrawerList);
- }
- @Override
- public void setTitle(CharSequence title) {
- mTitle = title;
- getActionBar().setTitle(mTitle);
- }
- /**
- * Fragment that appears in the "content_frame", shows a planet
- */
- public static class PlanetFragment extends Fragment {
- public static final String ARG_PLANET_NUMBER = "planet_number";
- public PlanetFragment() {
- // Empty constructor required for fragment subclasses
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View rootView = inflater.inflate(R.layout.fragment_planet, container, false);
- int i = getArguments().getInt(ARG_PLANET_NUMBER);
- String planet = getResources().getStringArray(R.array.planets_array)[i];
- int imageId = getResources().getIdentifier(planet.toLowerCase(Locale.getDefault()),
- "drawable", getActivity().getPackageName());
- ((ImageView) rootView.findViewById(R.id.image)).setImageResource(imageId);
- getActivity().setTitle(planet);
- return rootView;
- }
- }
- }
用到的图片资源官网的training页面都有的。
http://developer.android.com/training/implementing-navigation/nav-drawer.html#ActionBarIcon