Toolbar和沉浸式基类的封装
Toolbar基本使用和主题
在AppCompat主题出来之后,基本上都是用这个主题,方便管理整个app的主题风格。
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
colorPrimary一般是toolbar的颜色,colorPrimaryDark为statubar默认的颜色,注意:如果要使用toolbar作为导航栏的话,必须是NoActionBar的主题(也可以在Activity中用代码设置)。
建一个toolbar.xml:
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/toolbar"
android:layout_height="?android:actionBarSize"
android:background="@color/colorPrimary">
</android.support.v7.widget.Toolbar>
这里设置了toolbar最基本的属性,Toolbar是继承ViewGroup的,所以ViewGroup拥有的属性Toolbar一样也会有。?android:actionBarSize为设置高度,用系统默认的导航栏的高度,背景颜色用主题中设置的颜色。
以include方式引入,方便管理:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="test.xc.com.toolbartest.MainActivity">
<include layout="@layout/toobar"></include>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"/>
</LinearLayout>
toolbar本身就是一个View,只能每次嵌入布局中,但是为了统一,一般通过include方式引入。
在代码中引用:
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
通过setSupportActionBar(toolbar);toolbar就会拥有Actionbar的一些属性,可以通过ActionBar actionBar = getSupportActionBar();(注意这里是返回ActionBar )来操作toolbar。
运行效果是这样子的:
image.png
显然这不符合我们的要求,平时我们公司应用的开发头部有几种情况:左边有返回按钮,中间标题,字体白色,右边可能还有一个按钮,中间还有可能是搜索。面对这些情况,我们不可能不同的页面用不同的布局来表示,必须得要封装。下面就是改造的过程,一些基本的属性和不常用的就不讲了。
- 返回按钮
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
//设置是否显示返回按钮,注意:这里个方法是actionBar的方法
actionBar.setDisplayHomeAsUpEnabled(true);
//设置返回键的监听
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
image.png
返回按钮在现在的版本中默认是不显示的,需要调用actionBar.setDisplayHomeAsUpEnabled(true);方法才能显示,通过setNavigationOnClickListener()来监听事件,一般返回按钮都是销毁Activity,
当然,如果我们有设计自己的返回按钮的话只需要调用toolbar.setNavigationIcon(),来进行自定义。对应的xml属性为:app:navigationIcon="@mipmap/ic_drawer_home"
如果想要用系统的返回键而,要改变颜色呢?这就需要通过toolbar的主题来设置了。
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:toolbar="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:background="@color/colorPrimary"
android:theme="@style/toolbar_blue_theme"
toolbar:popupTheme="@style/ThemeOverlay.AppCompat.Light"
toolbar:subtitle=""
toolbar:title="">
<TextView
android:id="@+id/toolbar_center_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#ffffff"
android:textSize="18sp"
/>
</android.support.v7.widget.Toolbar>
需要给toolbar设置一个主题android:them,
<!-- ToolBar样式.-->
<style name="toolbar_blue_theme" parent="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<!-- 改变返回键、标题、菜单栏颜色.-->
<item name="colorControlNormal">@color/white</item>
</style>
colorControlNormal是给toolbar的返回键等设置颜色。如果要设置其他属性必须要用toolbar的自定义属性,toolbar说白了就是一个自定义View,系统没有的属性就要用自定义属性。
此外,toolbar具有高度自定义特性,我们可以防止一个TextView放到toolbar中间作为中间标题栏。
- toolbar的菜单
toobar的菜单和actionbar类似
<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_launcher"
android:title="@string/app_name"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_notification"
android:icon="@mipmap/ic_launcher"
android:title="@string/app_name"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_item1"
android:title="@string/app_name"
app:showAsAction="never" />
<item
android:id="@+id/actionresom2"
android:title="@string/app_name"
app:showAsAction="never" />
</menu>
//showAsAction这个属性的值有:
//1、always:使菜单项一直显示在ToolBar上。
//2、ifRoom:如果有足够的空间,这个值会使菜单项显示在ToolBar上。
//3、never:使菜单项永远都不出现在ToolBar上,在…的子项中显示。
//4、withText:使菜单项和它的图标,菜单文本一起显示。
代码中:
toolbar.inflateMenu(R.menu.toolbar_menu);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// item.getActionView();
// item.getIcon();
Toast.makeText(MainActivity.this,item.getTitle(),Toast.LENGTH_LONG).show();
return false;
}
});
这里有个小小的坑如果按照如上代码写,是没有任何效果的,是因为setSupportActionBar(toolbar);这句话的原因注释掉菜单栏就全部出来了。
需要重写activity的方法:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_menu,menu);
return true;
}
image.png
另外 还有有关菜单弹出框的主题:
<!-- ToolBar菜单样式.-->
<style name="popup_theme" parent="@style/ThemeOverlay.AppCompat.Dark">
<item name="android:background">@android:color/white</item>
<!--<item name="android:textColor">@android:color/holo_red_dark</item>-->
<item name="actionOverflowMenuStyle">@style/OverflowMenuStyle</item>
</style>
<style name="OverflowMenuStyle" parent="Widget.AppCompat.Light.PopupMenu.Overflow">
<!--设置不覆盖锚点-->
<item name="overlapAnchor">false</item>
</style>
- 分装
public abstract class BaseToolbarActivity extends BaseActivity implements Toolbar.OnMenuItemClickListener {
Toolbar mToolbar;
TextView mTitleName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(getContentViewLayoutID() != 0){
setContentView(getContentViewLayoutID());
initToolbar();
}
}
private void initToolbar() {
mToolbar = findViewById(R.id.toolbar);
mTitleName = findViewById(R.id.toolbar_center_title);
if (mToolbar != null){
mToolbar.setTitle("");
mTitleName.setText(getSubTitle());
setSupportActionBar(mToolbar);
if (isShowBack()){
showBack();
}
if(getMenu() != 0) {
mToolbar.inflateMenu(getMenu());
}
}
}
/**
* 版本号小于21的后退按钮图片
*/
private void showBack(){
//setNavigationIcon必须在setSupportActionBar(toolbar);方法后面加入
// mToolbar.setNavigationIcon(R.mipmap.icon_back);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onNavigationBtnClicked();
}
});
mToolbar.setOnMenuItemClickListener(this);
}
/**
* 右边菜单点击事件
* @param item
* @return
*/
@Override
public boolean onMenuItemClick(MenuItem item) {
return false;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if(getMenu() != 0) {
getMenuInflater().inflate(getMenu(), menu);
return true;
}
return super.onCreateOptionsMenu(menu);
}
/**
* 设置标题文本
*/
public abstract String getSubTitle();
/**
* 右边导航菜单栏
* @return
*/
public int getMenu() {
return 0;
}
public void onNavigationBtnClicked() {
finish();
}
/**
* 是否有返回按钮
* @return
*/
protected boolean isShowBack(){
return true;
}
}
一般有toolbar的activity还会继承一个基类,然后对toolbar进行封装,添加一些工厂方法让子类去选择实现。
参考:
http://www.jianshu.com/p/ae0013a4f71a
http://www.codeceo.com/article/android-toolbar-develop.html
http://www.jianshu.com/p/7b5c99e1cfa3