引言
本文通过自定义布局将DrawerLayout
和material-menu
封装起来,使在项目中使用更方便。这里面用到了DrawerLayout、material-menu、Toolbar,可以参考一些博文了解:
创建自定义view
由于向Toolbar或ListView这样的部件将会在不同的Activity中多次出现,为了提高代码的重用率,这里将它们单独放到部件文件中,用到时用include
引用(当然也可以在BaseActivity中部署,然后让用到的都继承BaseActivity)。这里创建一个MaterialDrawerLayout
布局组件来进行封装。
自定义Toolbar
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
</android.support.v7.widget.Toolbar>
自定义FrameLayout
<?xml version="1.0" encoding="utf-8"?>
<!--DrawerLayout 下面的Fragment-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
自定义Listview
<?xml version="1.0" encoding="utf-8"?>
<!-- 侧滑栏 -->
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/listView_drawer"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/white"
android:choiceMode="singleChoice"
android:divider="@color/item_normal_divider"
android:dividerHeight="0.4px" />
为导航栏的Item创建布局
<?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="@color/drawer_item"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeightSmall"/>
创建MaterialDrawerLayout布局
通过创建布局类的方式来创建自定义布局,这里创建一个MaterialDrawerLayout
布局类,使他继承DrawerLayout
,这这个类中主要完成DrawerLayout
和Toolbar
的绑定工作、对Toolbar
的导航按钮的监听(导航抽屉的打开个关闭事件监听)以及对导航抽屉中的Item的点击事件的监听和处理。
创建构造函数
这里实现了三个构造函数,其主要作用就是将该布局的父Activity
的上下文环境Context
传进来。
public MaterialDrawerLayout(Context context) {
this(context, null);
}
public MaterialDrawerLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MaterialDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
}
初始化ListView
<string-array name="drawer_menu">
<item>Menu 1</item>
<item>Menu 2</item>
<item>Menu 3</item>
<item>Menu 4</item>
</string-array>
这里使用strings.xml中的string数组资源做数据。
/**
* 初始化侧栏标签,并且为ListView Item的点击事件设置监听器
*/
private void initDrawerList(){
mDrawerListView = (ListView)findViewById(R.id.listView_drawer);
// 从strings.xml中获取数据
String [] items = getResources().getStringArray(R.array.drawer_menu);
// 生成适配器
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
mContext, R.layout.drawer_list_item, items);
// 为ListView设置适配器
mDrawerListView.setAdapter(adapter);
// 为ListView Item设置监听器
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
});
}
/**
* 对导航抽屉列表条目点击的处理
* @param position
*/
private void selectItem(int position){
// add your code
this.closeDrawer(mDrawerListView);
}
这里顺便为DrawerLayout的ListView的Item
设置了监听器,以及点击处理。
绑定toolbar
/**
* 将DrawerLayout和Toolbar绑定
* @param toolbar
*/
public void bindToolbar(Toolbar toolbar){
// 设置toolbar左上角的导航按钮图标
mMaterialMenuDrawable = new MaterialMenuDrawable(
mContext, Color.WHITE, MaterialMenuDrawable.Stroke.THIN);
toolbar.setNavigationIcon(mMaterialMenuDrawable);
// 初始化导航抽屉列表
initDrawerList();
// 为导航抽屉的打开关闭事件设置监听
setListener(toolbar);
}
为导航按钮设置监听
/**
* 为toolbar上的导航按钮设置监听
* @param toolbar
*/
private void setListener(Toolbar toolbar){
mDarwerToggle = new ActionBarDrawerToggle(
(Activity) mContext, this, toolbar, R.string.drawer_open, R.string.drawer_close){
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
isDrawerOpened = false;
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
isDrawerOpened = true;
}
public void onDrawerStateChanged(int newState) {
if(newState == DrawerLayout.STATE_IDLE){
if (isDrawerOpened){
mMaterialMenuDrawable.setIconState(MaterialMenuDrawable.IconState.ARROW);
}else{
mMaterialMenuDrawable.setIconState(MaterialMenuDrawable.IconState.BURGER);
}
}
}
public void onDrawerSlide(View drawerView, float slideOffset) {
mMaterialMenuDrawable.setTransformationOffset(
MaterialMenuDrawable.AnimationState.BURGER_ARROW,
isDrawerOpened ? 2 - slideOffset : slideOffset);
}
};
this.setDrawerListener(mDarwerToggle);
}
将自定义MaterialDrawerLayout应用到Activity中
首先隐藏项目的ActionBar
,以便引入toolbar
,参考Toolbar的简单使用。在activity_main.xml
中引入toolbar
以及materialdrawerlayout
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<!--Toolbar-->
<include layout="@layout/toolbar" />
<!--DrawerLayout-->
<com.example.customedrawerlayout.MaterialDrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--FragmentContent-->
<include layout="@layout/framelayout" />
<!--ListView-->
<include layout="@layout/listview_drawer" />
</com.example.customedrawerlayout.MaterialDrawerLayout>
</LinearLayout>
在MainActivity
中为toolbar
做些设置,然后调用MaterialDrawerLayout
的bindToolbar()
,如下所示:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerLayout = (MaterialDrawerLayout)findViewById(R.id.drawer_layout);
mToolbar = (Toolbar)findViewById(R.id.toolbar);
// 将toolbar设为标题栏
setSupportActionBar(mToolbar);
// 设置返回键可用
getSupportActionBar().setHomeButtonEnabled(true);
// 在Toolbar做最左边加上导航按钮
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mDrawerLayout.bindToolbar(mToolbar);
}
当然最终要的一点是,不要忘了引入相应的依赖。