Android侧滑菜单DrawerLayout

时间:2021-11-06 05:26:23

侧滑菜单控件DrawerLayoutSupport Library包中实现了侧滑菜单效果的控件,也许是因为第三方控件如MenuDrawer等的出现之后,Google借鉴而出现的产物。DrawerLayout分为侧边菜单和主内容两部分,侧边菜单可以根据手势展开与隐藏(DrawerLayout自身特性),主内容区的内容可以随着菜单的点击而变化,内容就要自己去实现啦。

下面的例子主要是根据官方文档移植过来的,简单的改动:

-----------------------界面布局----------------------------------------


<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/test_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/content_fr_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ListView
        android:id="@+id/left_drawer_lv"
        android:layout_width="200dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#111"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="1dp" />

</android.support.v4.widget.DrawerLayout>

布局说明:

1、创建Drawer Layout在需要抽屉菜单的界面,用DrawerLayout 作为界面根控件。
2、在DrawerLayout里面第一个View为当前界面主内容;第二个和第三个View为抽屉菜单内容。如果当前界面只需要一个抽屉菜单,则第三个View可以省略。
3、下面的例子中DrawerLayout里面包含两个View,第一个FrameLayout中是当前界面主要内容显示区域;第二个ListView为抽屉菜单内容。

--------------------代码部分------------------------------------

public class TestDrawerActivity extends Activity {
/**抽屉菜单(作为根布局) */
private DrawerLayout mDrawerLayout;
/**抽屉菜单之:左边菜单 */
private ListView mDrawerList;
/**抽屉菜单之:应用图标指示抽屉开关 */
private ActionBarDrawerToggle mDrawerToggle;
/**抽屉标题*/
private CharSequence mDrawerTitle;
/**抽屉菜单之:左边菜单数据 */
private String[] mLeftTitles;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_drawer);
findViewById();
setListeners();
initdata();
if (savedInstanceState == null) {
selectItem(0);
}
}


private void findViewById() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.test_drawer_layout);
mDrawerList = (ListView) findViewById(R.id.left_drawer_lv);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
/**菜单关闭操作*/
public void onDrawerClosed(View view) {
getActionBar().setTitle(mDrawerTitle);
invalidateOptionsMenu();
}


/**打开菜单操作 */
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
invalidateOptionsMenu();
}
};
}


private void setListeners() {
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
mDrawerLayout.setDrawerListener(mDrawerToggle);
}


private void initdata() {
/**菜单标题*/
mDrawerTitle = getTitle();
mLeftTitles = getResources().getStringArray(R.array.planets_array);
/**设置拉出导航菜单时阴影,官方示例不明显,可把图片背景修改一下*/
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mDrawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, mLeftTitles));
/**ActionBar操作模式开启*/
getActionBar().setDisplayHomeAsUpEnabled(false);
getActionBar().setHomeButtonEnabled(false);
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}


@Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) { return true; }
switch (item.getItemId()) {
case R.id.action_websearch:
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY, getActionBar().getTitle());
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
else {
Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show();
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}


/**菜单列表的点击操作*/
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 PlanetFragment();
Bundle args = new Bundle();
args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
fragment.setArguments(args);


FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_fr_layout, fragment).commit();
mDrawerList.setItemChecked(position, true);
setTitle(mLeftTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}


@Override
public void setTitle(CharSequence title) {
mDrawerTitle = title;
getActionBar().setTitle(mDrawerTitle);
}


@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}


@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}


public static class PlanetFragment extends Fragment {
public static final String ARG_PLANET_NUMBER = "planet_number";


public PlanetFragment() {
}


@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;
}
}
}
android.support.v4.widget.DrawerLayout使用时注意事项:

事项1:显示界面主要内容的View (上面的 FrameLayout ) 必须为DrawerLayout的第一个子View, 国为XML布局文件中的View顺序为Android系统中的 z-ordering顺序,而抽屉必须出现在内容之上。显示界面内容的View宽度和高度设置为和父View一样,原因在于当抽屉菜单不可见的时候,界面内容代表整个界面UI。

事项2:抽屉菜单 ( ListView) 必须使用android:layout_gravity属性设置水平的 gravity值 。如果要支持 right-to-left (RTL,从右向左阅读)语言 用 "start" 代替 "left" (当在 RTL语言运行时候,菜单出现在右侧)。抽屉菜单的宽度为 dp 单位而高度和父View一样。抽屉菜单的宽度建议不超过320dp,这样用户可以在菜单打开的时候看到部分内容界面。

事项3:如果需要监听菜单打开关闭事件,则需要调用 DrawerLayout类的 setDrawerListener() 函数,参数为 DrawerLayout.DrawerListener接口的实现。该接口提供了菜单打开关闭等事件的回调函数,例如 onDrawerOpened() 和onDrawerClosed()。

事项4:如果您的Activity使用了 action bar,则您可以使用Support库提供的 ActionBarDrawerToggle 类,该类实现了 DrawerLayout.DrawerListener接口,并且您还可以根据需要重写相关的函数。该类实现了菜单和Action bar相关的操作。当菜单显示的时候您应该根据情况隐藏ActionBar上的功能菜单并且修改ActionBar的标题,可以使用 ActionBarDrawerToggle 类来实现这些功能。

官网详细说明:http://developer.android.com/design/patterns/navigation-drawer.html