MaterialDesign学习篇(二),Toolbar、Dra
什么是Toolbar
Toolbar是应用的内容的标准工具栏,可以说是Actionbar的升级版,两者不是独立关系,要使用Toolbar还是得跟ActionBar扯上关系的。相比Actionbar,Toolbar最明显的一点就是变得很自由,可随处放置,因为它是作为一个ViewGroup来定义使用的,所以单纯使用ActionBar已经稍显过时了,它的一些方法已被标注过时。
Toolbar提供了一些可定制化修改的属性,这些可定制修改的属性在API文档中都有详细介绍,如:
- 设置导航栏图标;
- 设置App的logo;
- 支持设置标题和子标题;
- 支持添加一个或多个的自定义控件;
- 支持Action Menu;
如何使用Toolbar
演示如下:
步骤
一、在res目录中国,创建menu目录,并简历对应的xml文件,可任意命名,此处命名为menu_tool_bar.xml。
menu_tool_bar.xml中的代码:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!--右侧搜索操作条目-->
<item
android:id="@+id/action_search"
android:icon="@mipmap/ic_search"
android:title="@string/menu_search"
app:showAsAction="ifRoom" />
<!--右侧添加操作条目-->
<item
android:id="@+id/action_add"
android:icon="@mipmap/ic_add"
android:title="@string/menu_add"
app:showAsAction="ifRoom" />
<!--右侧设置条目,收起,不显示-->
<item
android:id="@+id/action_setting"
android:icon="@mipmap/ic_add"
android:title="@string/menu_setting"
app:showAsAction="never" />
<!--右侧设置帮助条目,收起,不显示-->
<item
android:id="@+id/action_help"
android:icon="@mipmap/ic_add"
android:title="@string/menu_help"
app:showAsAction="never" />
</menu>
这里配置的是toolbar右侧一些操作的条目,其中的showAsAction配置菜单项如何显示,有以下的值可选:
- always:使菜单项一直显示在ToolBar上。
- ifRoom:如果有足够的空间,这个值会使菜单项显示在ToolBar上。
- never:使菜单项永远都不出现在ToolBar上,在竖立的三点水(更多)图标的子项中显示。
- withText:使菜单项和它的图标,菜单文本一起显示。
我们设置了搜索和添加的菜单项showAsAction指定为ifRoom,在有足够的空间,它们是展示出来的,将设置和帮助的菜单项的showAsAction指定为never,所以它们就收起不显示,点击"更多"的图标的时候,它们才会显示。
二、布局文件中,使用Toolbar
在对应布局的xml文件中,配置toolbar:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
>
</android.support.v7.widget.Toolbar>
</LinearLayout>
由于Toolbar是在 Android 5.0才开始有的,我们需要在工程中引入 appcompat-v7的兼容包,由于AndroidStudio在创建项目的时候会默认添加v7包的依赖,所以比较省事,如果还再用Eclise开发的小伙伴,就需要自己添加v7包的依赖。
三、Activity中,对toolbar进行相关设置
1.调用Toolbar相关的API
public class ToolBarActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_tool_bar);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setBackgroundColor(getResources().getColor(R.color.toolbar_bg));//设置Toolbar的背景颜色
toolbar.setNavigationIcon(R.mipmap.ic_menu);//设置导航的图标
toolbar.setLogo(R.mipmap.ic_launcher);//设置logo
toolbar.setTitle("title");//设置标题
toolbar.setSubtitle("subtitle");//设置子标题
toolbar.setTitleTextColor(getResources().getColor(android.R.color.white));//设置标题的字体颜色
toolbar.setSubtitleTextColor(getResources().getColor(android.R.color.white));//设置子标题的字体颜色
setSupportActionBar(toolbar);
}
}
其中需要注意的是:
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
这句代码是不是觉得很眼熟,你以前肯定用过
requestWindowFeature(Window.FEATURE_NO_TITLE));
只是前面多了support,就和getFragmentManager()和getSupprotFragmentManager()差不多,由于ToolBarActivity继承AppCompatActivity,所以这里使用了supportRequestWindowFeature(Window.FEATURE_NO_TITLE),如果是继承Activity,则使用requestWindowFeature(Window.FEATURE_NO_TITLE)),这行代码是为了隐藏掉系统原先的导航栏,因为我们将使用Toolbar来代替。
隐藏导航栏的方法有两种:
-
在调用Activity的setContentView()方法之前,如果是继承AppCompatActivity,则调用supportRequestWindowFeature(Window.FEATURE_NO_TITLE),如果是继承Activity,则调用requestWindowFeature(Window.FEATURE_NO_TITLE))来隐藏导航栏。
-
为Activity设置一个NoActionBar的Theme,如Theme.AppCompat.Light.NoActionBar
以上代码运行后,效果如下:
是不是发现少了些什么,没错,少了右侧的搜索、添加菜单项。
此时,我们需要在Activity中,重写onCreateOptionsMenu()方法
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_tool_bar, menu);
return true;
}
getMenuInflater().inflate(R.menu.menu_tool_bar, menu);获取菜单填充器,将我们自定义的menu_tool_bar.xml文件填充。
2.设置菜单项的点击监听
要为菜单项设置点击监听,需要重写onOptionsItemSelected()方法,代码如下:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
String tip = "";
switch (id){
case android.R.id.home://对应navigationIcon的点击
tip = "菜单";
break;
case R.id.action_search:
tip = "搜索";
break;
case R.id.action_add:
tip = "添加";
break;
case R.id.action_setting:
tip = "设置";
break;
case R.id.action_help:
tip = "帮助";
break;
}
Toast.makeText(this, tip, Toast.LENGTH_SHORT).show();
return super.onOptionsItemSelected(item);
}
在该方法中,我们需要对id进行判断,在menu_tool_bar.xml文件中,对应的菜单项我们都有给予对应的id,如果想对navigationIcon做点击的处理,则当id为android.R.id.home的时候,做相关操作。
显示菜单项和设置点击监听的另一方法
上面提到如果想显示右侧的菜单项,则重写onCreateOptionsMenu()方法将对应的xml文件填充,需要设置点击监听,则重写onOptionsItemSelected()方法,根据id进行判断,做相关处理。还有另外一种方法实现上述的两个功能,不需要重写这两个方法,代码如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_tool_bar);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setBackgroundColor(getResources().getColor(R.color.toolbar_bg));//设置Toolbar的背景颜色
toolbar.setNavigationIcon(R.mipmap.ic_menu);//设置导航的图标
toolbar.setLogo(R.mipmap.ic_launcher);//设置logo
toolbar.setTitle("title");//设置标题
toolbar.setSubtitle("subtitle");//设置子标题
toolbar.setTitleTextColor(getResources().getColor(android.R.color.white));//设置标题的字体颜色
toolbar.setSubtitleTextColor(getResources().getColor(android.R.color.white));//设置子标题的字体颜色
//设置右上角的填充菜单
toolbar.inflateMenu(R.menu.menu_tool_bar);
//设置导航图标的点击事件
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(ToolBarActivity.this, "菜单", Toast.LENGTH_SHORT).show();
}
});
//设置右侧菜单项的点击事件
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId();
String tip = "";
switch (id) {
case R.id.action_search:
tip = "搜索";
break;
case R.id.action_add:
tip = "添加";
break;
case R.id.action_setting:
tip = "设置";
break;
case R.id.action_help:
tip = "帮助";
break;
}
Toast.makeText(ToolBarActivity.this, tip, Toast.LENGTH_SHORT).show();
return false;
}
});;
}
当调用Toolbar的inflateMenu()方法加载menu布局时,无需再调用setSupportActionBar(),否则加载的是onCreateOptionsMenu()中的布局,点击时不会回调onOptionsItemSelected()方法,需要调用Toolbar的setOnMenuItemClickListener()方法,设置点击的监听,根据对应的id进行判断和处理,与onOptionsItemSelected()中处理不同的是,对应navigationIcon的点击事件,是在Toolbar的setNavigationOnClickListener()方法中进行处理。
Toolbar中添加自定义view
一开始我们提到Toolbar可以进行定制化修改,除了navigationIcon、logo、标题、子标题、菜单项外,还可以添加一些自定义控件(系统原有或自己写的控件),使用的方法很简单,布局文件中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="custom"
android:textColor="@android:color/white"
android:textSize="16sp"
/>
</android.support.v7.widget.Toolbar>
</LinearLayout>
效果如下:
什么是DrawerLayout
DrawerLayout是Support Library包中实现了侧滑菜单效果的控件,可以说DrawerLayout是因为第三方控件如MenuDrawer等的出现之后,Google借鉴而出现的产物。DrawerLayout分为侧边菜单和主内容区两部分,侧边菜单可以根据手势展开与隐藏(DrawerLayout自身特性),主内容区的内容可以随着菜单的点击而变化(这需要使用者自己实现)。
结合DrawerLayout效果如下:
Toolbar + DrawerLayout 在日常开发中经常使用到,一般是那种侧滑菜单栏的App。
使用DrawerLayout的步骤
一、布局文件中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
... //此处省略toolbar
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--content-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/content_text"
android:gravity="center"
android:layout_gravity="center"
android:textSize="16sp"
/>
</FrameLayout>
<!--menu-->
<FrameLayout
android:layout_width="180dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="@android:color/white"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:textSize="16sp"
android:text="@string/menu_text"
android:gravity="center"
android:layout_gravity="center"
/>
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
使用DrawerLayout,需要添加v4包的依赖,AS创建项目的时候自带v4包的依赖,所以可以直接引用到。DrawerLayout中包括两个childView,一个为内容区域的根布局,另一个为侧边栏的根布局,如果是侧边栏的布局,需要指定其android:layout_gravity="left"或者android:layout_gravity="start"。需要注意的是,作为侧边栏的布局需要放置在内容区域下面,否则其子条目的点击事件将无法响应。
二、Activity中,将Toolbar和DrawerLayout结合
private void initDrawerLayout() {
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,mToolbar, R.string.open, R.string.close);
mDrawerToggle.syncState();;///将ActionDrawerToggle与DrawerLayout的状态同步
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
使用DrawerLayout的小案例,效果如下
一、修改布局文件为:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
... //此处省略toolbar
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--content-->
<FrameLayout
android:id="@+id/fl_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</FrameLayout>
<!--menu-->
<ListView
android:id="@+id/lv_list"
android:layout_width="180dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="@android:color/white"
/>
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
二、Activity中:
@Override
protected void onCreate(Bundle savedInstanceState) {
...
initView();
initToolBar();
initMenuTitles();
initFragments();
initDrawerLayout();
}
其中,为侧边栏的listView添加adapter,并设置条目的点击事件
/**
* 设置左侧菜单条目的标题
*/
private void initMenuTitles() {
mMenuTitles = getResources().getStringArray(R.array.menuTitles);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mMenuTitles);
mLvList.setAdapter(arrayAdapter);
mLvList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
switchFragment(position);//切换fragment
mDrawerLayout.closeDrawers();//收起DrawerLayout
}
});
}
/**
* 切换fragment
* @param index 下标
*/
private void switchFragment(int index) {
ContentFragment contentFragment = mFragments.get(index);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.fl_content,contentFragment);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.commit();
}
好了,到此为止,ToolBar和DrawerLayout的使用,相信已经基本掌握了。需要源码的可以查看: