在本教程中,我们将在Android应用程序 中实现一个** 导航抽屉** 。Android导航抽屉是一个滑动菜单,是一个重要的用户界面组件。你会在大多数Android应用程序中看到导航抽屉,它就像网站中的导航菜单栏。
Android导航抽屉
Android导航抽屉是一个向左滑动的菜单,用于显示应用程序中的重要链接。导航抽屉使您可以轻松地在这些链接之间来回导航。默认情况下,它是不可见的,需要通过向左滑动或在ActionBar中单击其图标来打开它。更广泛地说,导航抽屉是一个覆盖面板,它取代了专门用于显示应用程序中的所有选项和链接的活动屏幕。在这篇Android导航抽屉教程中,我们将使用Android支持库中的抽屉布局API来实现导航抽屉。我们将展示可以从抽屉项打开的3个片段视图。
Android导航抽屉项目结构
Android导航抽屉示例
要实现导航抽屉,我们首先需要添加android.support.v4.widget.DrawerLayout
作为活动布局的根,如下所示。active_main.xml
1<android.support.v4.widget.DrawerLayout
2 xmlns:android="https://schemas.android.com/apk/res/android"
3 android:id="@+id/drawer_layout"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent" >
6
7 <LinearLayout
8 android:layout_width="match_parent"
9 android:layout_height="match_parent"
10 android:orientation="vertical">
11
12 <LinearLayout
13 android:id="@+id/container_toolbar"
14 android:layout_width="match_parent"
15 android:layout_height="wrap_content"
16 android:orientation="vertical">
17
18 <include
19 android:id="@+id/toolbar"
20 layout="@layout/toolbar" />
21 </LinearLayout>
22
23 <FrameLayout
24 android:id="@+id/content_frame"
25 android:layout_width="match_parent"
26 android:layout_height="match_parent" />
27
28 </LinearLayout>
29
30 <ListView
31 android:id="@+id/left_drawer"
32 android:layout_width="240dp"
33 android:layout_height="match_parent"
34 android:layout_gravity="start"
35 android:background="#FFFFFF"
36 android:choiceMode="singleChoice"
37 android:divider="@android:color/darker_gray"
38 android:dividerHeight="1dp" />
39
40</android.support.v4.widget.DrawerLayout>
导航抽屉中的菜单选项以ListView的形式存储。每个选项都会在FrameLayout中打开。我们在这里使用了工具栏 来代替ActionBar。工具栏是从Android 5.0开始引入的,是ActionBar的泛化。它给了我们更多的控制和修改的灵活性,并且更容易与层次结构中的其他视图交错。布局工具栏在下面给出的XML布局中定义。Toolbar.xml
1<android.support.v7.widget.Toolbar xmlns:android="https://schemas.android.com/apk/res/android"
2 xmlns:local="https://schemas.android.com/apk/res-auto"
3 android:id="@+id/toolbar"
4 android:layout_width="match_parent"
5 android:layout_height="wrap_content"
6 android:minHeight="?attr/actionBarSize"
7 android:background="?attr/colorPrimary"
8 local:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
9 local:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
在使用工具栏时,我们需要在style es.xml中使用主题Theme.AppCompat.NoActionBar
。导航抽屉中的ListView行的布局如下所示。List_view_Item_row.xml
1<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
2 android:layout_width="match_parent"
3 android:layout_height="wrap_content"
4 android:background="?android:attr/activatedBackgroundIndicator"
5 android:minHeight="?android:attr/listPreferredItemHeightSmall"
6 android:padding="10dp" >
7
8 <ImageView
9 android:id="@+id/imageViewIcon"
10 android:layout_width="wrap_content"
11 android:layout_height="wrap_content"
12 android:layout_alignParentLeft="true"
13 android:layout_alignParentTop="true"
14 android:paddingRight="10dp" />
15
16 <TextView
17 android:id="@+id/textViewName"
18 android:layout_width="wrap_content"
19 android:layout_height="wrap_content"
20 android:layout_centerVertical="true"
21 android:layout_toRightOf="@+id/imageViewIcon"
22 android:paddingRight="10dp"
23 android:text="Item Name"
24 android:textColor="@android:color/black"
25 android:textAppearance="?android:attr/textAppearanceListItemSmall"
26 />
27
28</RelativeLayout>
如下所示,导航抽屉项被放在字符串.xml文件中的字符串数组中。字符串.xml
1<string-array name="navigation_drawer_items_array">
2 <item>Connect</item>
3 <item>Fixtures</item>
4 <item>Table</item>
5 </string-array>
Java类用于定义抽屉列表项的对象。DataModel.java
1package com.journaldev.navigationdrawer;
2
3public class DataModel {
4
5 public int icon;
6 public String name;
7
8 // Constructor.
9 public DataModel(int icon, String name) {
10
11 this.icon = icon;
12 this.name = name;
13 }
14}
抽屉项以ListView的形式存储。因此,我们需要使用Adapter Class将该数据提供给Activity类。DrawerItemCustomAdapter.java
1package com.journaldev.navigationdrawer;
2
3import android.app.Activity;
4import android.content.Context;
5import android.view.LayoutInflater;
6import android.view.View;
7import android.view.ViewGroup;
8import android.widget.ArrayAdapter;
9import android.widget.ImageView;
10import android.widget.TextView;
11
12public class DrawerItemCustomAdapter extends ArrayAdapter<DataModel> {
13
14 Context mContext;
15 int layoutResourceId;
16 DataModel data[] = null;
17
18 public DrawerItemCustomAdapter(Context mContext, int layoutResourceId, DataModel[] data) {
19
20 super(mContext, layoutResourceId, data);
21 this.layoutResourceId = layoutResourceId;
22 this.mContext = mContext;
23 this.data = data;
24 }
25
26 @Override
27 public View getView(int position, View convertView, ViewGroup parent) {
28
29 View listItem = convertView;
30
31 LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
32 listItem = inflater.inflate(layoutResourceId, parent, false);
33
34 ImageView imageViewIcon = (ImageView) listItem.findViewById(R.id.imageViewIcon);
35 TextView textViewName = (TextView) listItem.findViewById(R.id.textViewName);
36
37 DataModel folder = data[position];
38
39 imageViewIcon.setImageResource(folder.icon);
40 textViewName.setText(folder.name);
41
42 return listItem;
43 }
44}
下面给出了MainActivity.java的源代码。MainActivity.java
1package com.journaldev.navigationdrawer;
2
3import android.support.v4.app.Fragment;
4import android.support.v4.app.FragmentManager;
5import android.support.v4.widget.DrawerLayout;
6import android.support.v7.app.AppCompatActivity;
7import android.os.Bundle;
8import android.support.v7.widget.Toolbar;
9import android.util.Log;
10import android.view.MenuItem;
11import android.view.View;
12import android.widget.AdapterView;
13import android.widget.ListView;
14
15public class MainActivity extends AppCompatActivity {
16
17 private String[] mNavigationDrawerItemTitles;
18 private DrawerLayout mDrawerLayout;
19 private ListView mDrawerList;
20 Toolbar toolbar;
21 private CharSequence mDrawerTitle;
22 private CharSequence mTitle;
23 android.support.v7.app.ActionBarDrawerToggle mDrawerToggle;
24
25 @Override
26 protected void onCreate(Bundle savedInstanceState) {
27 super.onCreate(savedInstanceState);
28 setContentView(R.layout.activity_main);
29 mTitle = mDrawerTitle = getTitle();
30 mNavigationDrawerItemTitles= getResources().getStringArray(R.array.navigation_drawer_items_array);
31 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
32 mDrawerList = (ListView) findViewById(R.id.left_drawer);
33
34 setupToolbar();
35
36 DataModel[] drawerItem = new DataModel[3];
37
38 drawerItem[0] = new DataModel(R.drawable.connect, "Connect");
39 drawerItem[1] = new DataModel(R.drawable.fixtures, "Fixtures");
40 drawerItem[2] = new DataModel(R.drawable.table, "Table");
41 getSupportActionBar().setDisplayHomeAsUpEnabled(false);
42 getSupportActionBar().setHomeButtonEnabled(true);
43
44 DrawerItemCustomAdapter adapter = new DrawerItemCustomAdapter(this, R.layout.list_view_item_row, drawerItem);
45 mDrawerList.setAdapter(adapter);
46 mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
47 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
48 mDrawerLayout.setDrawerListener(mDrawerToggle);
49 setupDrawerToggle();
50
51 }
52
53 private class DrawerItemClickListener implements ListView.OnItemClickListener {
54
55 @Override
56 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
57 selectItem(position);
58 }
59
60 }
61
62 private void selectItem(int position) {
63
64 Fragment fragment = null;
65
66 switch (position) {
67 case 0:
68 fragment = new ConnectFragment();
69 break;
70 case 1:
71 fragment = new FixturesFragment();
72 break;
73 case 2:
74 fragment = new TableFragment();
75 break;
76
77 default:
78 break;
79 }
80
81 if (fragment != null) {
82 FragmentManager fragmentManager = getSupportFragmentManager();
83 fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
84
85 mDrawerList.setItemChecked(position, true);
86 mDrawerList.setSelection(position);
87 setTitle(mNavigationDrawerItemTitles[position]);
88 mDrawerLayout.closeDrawer(mDrawerList);
89
90 } else {
91 Log.e("MainActivity", "Error in creating fragment");
92 }
93 }
94
95 @Override
96 public boolean onOptionsItemSelected(MenuItem item) {
97
98 if (mDrawerToggle.onOptionsItemSelected(item)) {
99 return true;
100 }
101
102 return super.onOptionsItemSelected(item);
103 }
104
105 @Override
106 public void setTitle(CharSequence title) {
107 mTitle = title;
108 getSupportActionBar().setTitle(mTitle);
109 }
110
111 @Override
112 protected void onPostCreate(Bundle savedInstanceState) {
113 super.onPostCreate(savedInstanceState);
114 mDrawerToggle.syncState();
115 }
116
117 void setupToolbar(){
118 toolbar = (Toolbar) findViewById(R.id.toolbar);
119 setSupportActionBar(toolbar);
120 getSupportActionBar().setDisplayShowHomeEnabled(true);
121 }
122
123 void setupDrawerToggle(){
124 mDrawerToggle = new android.support.v7.app.ActionBarDrawerToggle(this,mDrawerLayout,toolbar,R.string.app_name, R.string.app_name);
125 //This is necessary to change the icon of the Drawer Toggle upon state change.
126 mDrawerToggle.syncState();
127 }
128}
在上面的代码中,getSupportActionBar().setDisplayHomeAsUpEnabled(false);
用于隐藏默认的后退按钮。在这段代码中,我们使用了一个DrawerItemClickListener
类,它加载使用FragmentManager单击的列表项的相应片段。此外,工具栏的标题将更改为使用setTitle(mNavigationDrawerItemTitles[position]);
.单击的列表项片段类及其各自的布局如下所示。ConnectFragment.java
1package com.journaldev.navigationdrawer;
2
3import android.os.Bundle;
4import android.support.v4.app.Fragment;
5import android.view.LayoutInflater;
6import android.view.View;
7import android.view.ViewGroup;
8
9public class ConnectFragment extends Fragment {
10
11 public ConnectFragment() {
12 }
13
14 @Override
15 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
16
17 View rootView = inflater.inflate(R.layout.fragment_connect, container, false);
18
19 return rootView;
20 }
21
22}
上述片段的布局定义如下。Fragment_Connect.xml
1<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
2 xmlns:tools="https://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:orientation="vertical">
6
7 <TextView
8 android:id="@+id/label"
9 android:layout_alignParentTop="true"
10 android:layout_marginTop="100dp"
11 android:layout_width="fill_parent"
12 android:layout_height="wrap_content"
13 android:gravity="center_horizontal"
14 android:textSize="45dp"
15 android:text="Connect"
16 android:textStyle="bold"/>
17
18 <TextView
19 android:layout_below="@id/label"
20 android:layout_centerInParent="true"
21 android:layout_width="fill_parent"
22 android:layout_height="wrap_content"
23 android:textSize="12dp"
24 android:layout_marginTop="10dp"
25 android:gravity="center_horizontal"
26 android:text="Edit fragment_connect.xml to change the appearance"
27 android:id="@+id/textView2" />
28
29</RelativeLayout>
另外两个项目的定义方式与上面完全相同,因此我们在这里跳过它。
导航抽屉Android示例输出
下面是我们的导航抽屉Android示例应用程序产生的输出。这将结束安卓导航抽屉示例教程。您可以通过下面的链接下载最终的Android导航抽屉项目 。