转载请标明出处:http://www.jianshu.com/p/7b5c99e1cfa3
本文出自:Jlanglang
前言:
因为需要封装toolbar,所以彻底的研究了下toolbar,
以前只是简单用用,现在发现完全用起来很多坑,总结一下.
先来张效果图:
Toolbar的结构其实很简单:
1.NavigationIcon
2.Logo
3.Title
4.subTitle
5.menu.
常用的:1,3,5
友情提示:
getSupportActionBar()一定要在setSupportActionBar(Toolbar toolbar)之后调用
先说常用的:
1.NavigationIcon的几个方法
//设置是否添加显示NavigationIcon.如果要用
void setDisplayHomeAsUpEnabled(boolean showHomeAsUp);
//设置NavigationIcon的icon.可以是Drawable ,也可以是ResId
void setNavigationIcon(@Nullable Drawable icon);
void setNavigationIcon(@DrawableRes int resId)
//设置NavigationIcon的点击监听.
void setNavigationOnClickListener(OnClickListener listener);
具体使用:
Toolbar mToolbar = (Toolbar)findViewById(R.id.toolbar)
//设置Toolbar
setSupportActionBar(mToolbar);
//显示NavigationIcon,这个方法是ActionBar的方法.Toolbar没有这个方法.
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
//设置icon
mToolbar.setNavigationIcon(drawable);
//设置监听.必须在setSupportActionBar()之后调用
mToolbar.setNavigationOnClickListener(clickListener);
总结几个坑:
1.必须先 setSupportActionBar(mToolbar).
2.setDisplayHomeAsUpEnabled(true)是ActionBar的方法.
3.setNavigationOnClickListener()必须要在setSupportActionBar()之后调用才能生效.因为setSupportActionBar(Toolbar),会将Toolbar转换成Acitionbar.点击监听也会重新设置.
2.Title
几个方法:
//是否显示
getSupportActionBar().setDisplayShowTitleEnabled(boolean showTitle);
//设置title.
getSupportActionBar().setTitle(title);
//设置title.
Toolbar.setTitle(title);
//设置Margin边距.
Toolbar.setTitleMargin();
//设置字体.
Toolbar.setTitleTextAppearance();
//设置字的颜色
Toolbar.setTitleTextColor(int color);
总结:
使用比较简单.基本看方法名就知道是干嘛的了.也没什么坑.
Toolbar直接设置title或者getSupportActionBar()再设置title都可以.
3 Menu菜单
这玩意用起来有点蛋疼.坑挺多的.
先说创建:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//写一个menu的资源文件.然后创建就行了.
getMenuInflater().inflate(R.menu.menu,menu);
return super.onCreateOptionsMenu(menu);
}
//showAsAction这个属性的值有:
//1、always:使菜单项一直显示在ToolBar上。
//2、ifRoom:如果有足够的空间,这个值会使菜单项显示在ToolBar上。
//3、never:使菜单项永远都不出现在ToolBar上,在…的子项中显示。
//4、withText:使菜单项和它的图标,菜单文本一起显示。
设置Menu点击
/**
* 菜单项被点击时调用,也就是菜单项的监听方法。
* 通过这几个方法,可以得知,对于Activity,同一时间只能显示和监听一个Menu 对象.
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
//通过设置toolbar进行监听,在setSupportActionBar(Toolbar toolbar)之前设置可能会失 效.
Toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
return false;
}
});
Menu的一些操作
/**
* 每次菜单被关闭时调用.
*菜单被关闭有三种情形:
*1.展开menu的按钮被再次点击
*2.back按钮被点击
*3.用户选择了某一个菜单项
*/
@Override
public void onOptionsMenuClosed(Menu menu) {
super.onOptionsMenuClosed(menu);
}
/**
* 在onCreateOptionsMenu执行后,菜单被显示前调用;如果菜单已经被创建,则在菜单显示前被调用。 同样的,
* 返回true则显示该menu,false 则不显示; (可以通过此方法动态的改变菜单的状态,比如加载不同的菜单等)
*/
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
return super.onPrepareOptionsMenu(menu);
}
/**
* 显示menu的icon,通过反射,设置Menu的icon显示.
* @param view
* @param menu
* @return
*/
@Override
protected boolean onPrepareOptionsPanel(View view, Menu menu) {
if (menu != null) {
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
try{
Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
} catch (Exception e) {
Log.e(getClass().getSimpleName(), "onMenuOpened...unable to set icons for overflow menu", e);
}
}
}
return super.onPrepareOptionsPanel(view, menu);
}
style的配置:
style的配置感觉挺恶心的.坑挺多的
基本的配置:
style的有些方法必须是Sdk21以上才能用,所以得这样
创建一个values-v21的文件夹,再写一个style.
还得做一些配置.
普通values中的style改成如下:
values-v21中的style如下:
使用这个style
style="@style/base_toolbar"
-----------------------------------------------分割线 -----------------------------------------------
现在来说说style中的坑:
1.app:theme ------------------toolbar的主题
2.app:popupTheme------------弹出的menu的主题.
继承的是ThemeOverlay.AppCompat:
如果使用的是Dark系列的主题,那么字体就是白色的.menu菜单背景是黑色
如果使用的是Light系列的主题,那么字体和图标就是黑色的.menu菜单背景是白色
下面说说这里坑的地方:
1.修改toolbar的字体
2.修改Toolbar的menu折叠图标和NavigationIcon的颜色
效果图:
3.修改menu的字体颜色(大坑):
既然是menu菜单的内容,当然是修改popup_theme了.
找了很多资料,发现都不正确.
比如说设置android:actionMenuTextColor这个属性
后来干脆一个个属性试好了,发现其实没那么麻烦..
效果:
4.menu菜单的显示位置
默认是这样的:
会遮盖toolbar
可以修改popuptheme的这个属性来设置:
- false
有些资料说要这么设置:
其实没必要,可以直接在app:popupTheme
的style里面设置overlapAnchor这个属性就好了.
但是,一定是要在app:popupTheme
的style里面设置,而不是app:theme
的style里面设置.
最终效果如下:
最终效果的style代码:
values-v21的style的代码:
toolbar布局的代码
到此一般的基本设置就写完了.
------------------------------------------------------------------------------------------`
2017-6-21更新
fragment使用menu菜单的正确姿势
坑点:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
1.在frgament里面这个方法就是坑爹的
2.即使 setHasOptionsMenu(true);
也不创建,跳个页面返回回来结果有了.
3.但如果是viewpager+多frgament这种.会造成错乱.其他的frgament也会有menu
4.style配置无效!!
正确姿势:
哥直接代码设置还不行嘛.不配置了
以下代码在setSupportActionBar()
之前调用
//设置popupstyle.比如是否覆盖描点,背景,字体颜色什么的.必须在inflateMenu()之前设置
mToolbar.setPopupTheme(R.style.popup_theme);
//用Toolbar创建menu
mToolbar.inflateMenu(R.menu.main_home_menu);
//拿到Menu
Menu menu = mToolbar.getMenu();
//下面的这段代码是为了让menu菜单折叠样式时,展开能显示icon图标.不然icon图标不会显示.(感觉很坑)
if (menu != null) {
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
try {
MenuBuilder menuBuilder = (MenuBuilder) menu;
menuBuilder.setOptionalIconsVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
交流群:493180098,这是个很少吹水,交流学习的群.
APP开发维护咨询群 : 492685472 ,承接APP迭代.开发维护.咨询业务,付费快速解决问题.