上一篇文章介绍了ToolBar的使用方法,在日常开发中ToolBar会在很多的Activity中同时使用,所以我们有必要把ToolBar进行封装,方便调用。
基本思路是写一个单独的ToolBar的文件,再写一个基类Activity重写它的setContentView()方法,在这个方法里添加ToolBar。具体代码如下:
package bcjm.myapplication;
import android.support.annotation.LayoutRes;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
/**
* Created by lx on 2017/11/24.
*/
public abstract class BaseActivity extends AppCompatActivity {
protected Toolbar toolbar;
private boolean showToolBar = true;
protected TitleBarView titleBarView;
@Override
public void setContentView(@LayoutRes int layoutResID) {
//使用自定义的TitleBarView,不推荐
if (isShowTitleBar()) {
titleBarView = new TitleBarView(this);
titleBarView.setBtnLeftOnclickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setId(R.id.ll_container_id);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
linearLayout.addView(titleBarView);
View view = getLayoutInflater().inflate(layoutResID, null);
linearLayout.addView(view, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
super.setContentView(linearLayout);
//强烈推荐使用ToolBar
} else if (isShowToolBar()) {
toolbar = (Toolbar) getLayoutInflater().inflate(R.layout.toolbar, null);
toolbar.setTitle("");
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setId(R.id.ll_container_id);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
linearLayout.addView(toolbar, LinearLayout.LayoutParams.MATCH_PARENT, DensityUtil.dipToPixels(this, 50));
View view = getLayoutInflater().inflate(layoutResID, null);
linearLayout.addView(view, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
super.setContentView(linearLayout);
} else {
super.setContentView(layoutResID);
}
StatusBarUtils.setColor(this, R.color.colorPrimaryDark);
}
/***
* 如果需要设置TitleBarView 重写这个方法 setshowToolBar(false);
* @return
*/
protected boolean isShowTitleBar() {
return false;
}
protected void setShowToolBar(boolean isShow) {
showToolBar = isShow;
}
protected boolean isShowToolBar() {
return showToolBar;
}
/**
* 设置返回按钮是否可见
*
* @param visible
*/
protected void setBackVisible(boolean visible) {
getSupportActionBar().setDisplayHomeAsUpEnabled(visible);
}
protected abstract void initTitleView();
protected abstract void initView();
}
这里提供了2种方式显示标题栏,一种是使用自定义控件TitleBarView来显示标题栏,另一种使用ToolBar来显示标题栏。这里强烈推荐ToolBar,如果ToolBar不满足你的需求,可以使用TitleBarView来自定义标题栏。使用TitleBarView是需要setShowToolBar(false),并重写isShowTitleBar()方法。
改变状态栏颜色包括改变状态栏背景颜色和状态栏字体颜色
在应用主题style中可以通过设置:
<item name="colorPrimaryDark">@color/colorPrimaryDarkitem>
但这个只有在android 5.0版本及以上才生效。在android 5.0以下是没有效果的默认是黑色背景白色字体。
我们也可以通过代码来动态设置状态栏背景颜色,并可以适配到android 4.4及以上。代码如下:
import android.app.Activity;
import android.os.Build;
import android.support.annotation.ColorRes;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
/**
* Created by lx on 2017/11/28.
*/
public class StatusBarUtils {
/**
* 设置状态栏颜色
* @param activity
* @param color
*/
public static void setColor(Activity activity,@ColorRes int color){
//如果版本大于等于5.0,直接用系统的api
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().setStatusBarColor(activity.getResources().getColor(color));
//如果版本大于等于4.4小于5.0,先把状态栏设置为透明的,再加一个View上去;小于android4.4系统
//不支持设置透明状态栏,所以无法更改
}else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT){
//设置透明 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//获取屏幕的根布局
ViewGroup viewGroup = (ViewGroup) activity.getWindow().getDecorView();
int count = viewGroup.getChildCount();
boolean isAdd = false;
int j = -1;
for (int i = 0; i < count; i++) {
View view = viewGroup.getChildAt(i);
if (view instanceof StatusBarView) {
j = i;
isAdd = true;
break;
}
}
if (j != -1 && isAdd && viewGroup.getChildAt(j) instanceof StatusBarView) {
StatusBarView statusview = (StatusBarView) viewGroup.getChildAt(j);
statusview.setBackgroundColor(activity.getResources().getColor(color));
} else {
StatusBarView statusBarView = new StatusBarView(activity);
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity));
statusBarView.setLayoutParams(layoutParams);
statusBarView.setBackgroundColor(activity.getResources().getColor(color));
viewGroup.addView(statusBarView);
}
setRootView(activity, true);
}
}
/**
* 设置根布局参数
*/
private static void setRootView(Activity activity) {
ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content);
for (int i = 0, count = parent.getChildCount(); i < count; i++) {
View childView = parent.getChildAt(i);
if (childView instanceof ViewGroup) {
//系统会自动的调整显示区域来实现详情的控件不会被遮住
childView.setFitsSystemWindows(true);
((ViewGroup) childView).setClipToPadding(true);
}
}
}
public static int getStatusBarHeight(Activity activity){
int resId=activity.getResources().getIdentifier("status_bar_height","dimen","android");
int height=activity.getResources().getDimensionPixelSize(resId);
return height;
}
}
在android 4.4利用WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS透明状态栏的属性,自己添加一个和状态栏一样大小的View来设置状态栏背景颜色。目前对于android4.4以下的系统是无法设置状态背景颜色的。
目前就小米和魅族提供相应的方法来修改状态栏颜色还有android 6.0及以上系统支持修改状态栏颜色。我把他们简单封装了一些:部分代码如下:
/**
*设置状态栏黑色字体图标,
* 适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android
* @param activity
* @return 1:MIUUI 2:Flyme 3:android6.0
*/
public static int StatusBarLightMode(Activity activity){
int result=0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//如果是小米系统
if(SystemUtil.getSystem().equals(SystemUtil.SYS_MIUI)
&&MIUISetStatusBarLightMode(activity,true)){
result=1;
//如果是魅族系统
}else if(SystemUtil.getSystem().equals(SystemUtil.SYS_FLYME)) {
StatusbarColorUtils.setStatusBarDarkIcon(activity, true);
result = 2;
//android 6.0系统
} else if (Build.VERSION.SDK_INT >=23) {
activity.getWindow().setStatusBarColor(Color.WHITE);
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
// activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|0x00002000);
result=3;
}
}
return result;
}
/**
* 设置状态栏字体图标为深色,需要MIUIV6以上
* @param activity a
* @param dark 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回true
*
*/
public static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
boolean result = false;
if (activity != null) {
Class clazz = activity.getWindow().getClass();
try {
int darkModeFlag = 0;
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
if(dark){
extraFlagField.invoke(activity.getWindow(),darkModeFlag,darkModeFlag);//状态栏透明且黑色字体
}else{
extraFlagField.invoke(activity.getWindow(), 0, darkModeFlag);//清除黑色字体
}
result=true;
}catch (Exception e){
}
}
return result;
}
判断手机系统帮助类
public class SystemUtil {
public static final String SYS_EMUI = "sys_emui";
public static final String SYS_MIUI = "sys_miui";
public static final String SYS_FLYME = "sys_flyme";
private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name";
private static final String KEY_MIUI_INTERNAL_STORAGE = "ro.miui.internal.storage";
private static final String KEY_EMUI_API_LEVEL = "ro.build.hw_emui_api_level";
private static final String KEY_EMUI_VERSION = "ro.build.version.emui";
private static final String KEY_EMUI_CONFIG_HW_SYS_VERSION = "ro.confg.hw_systemversion";
public static String getSystem(){
String SYS="";
try {
Properties prop= new Properties();
prop.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));
if(prop.getProperty(KEY_MIUI_VERSION_CODE, null) != null
|| prop.getProperty(KEY_MIUI_VERSION_NAME, null) != null
|| prop.getProperty(KEY_MIUI_INTERNAL_STORAGE, null) != null){
SYS = SYS_MIUI;//小米
}else if(prop.getProperty(KEY_EMUI_API_LEVEL, null) != null
||prop.getProperty(KEY_EMUI_VERSION, null) != null
||prop.getProperty(KEY_EMUI_CONFIG_HW_SYS_VERSION, null) != null){
SYS = SYS_EMUI;//华为
}else if(getMeizuFlymeOSFlag().toLowerCase().contains("flyme")){
SYS = SYS_FLYME;//魅族
};
} catch (IOException e){
e.printStackTrace();
return SYS;
}
return SYS;
}
public static String getMeizuFlymeOSFlag() {
return getSystemProperty("ro.build.display.id", "");
}
private static String getSystemProperty(String key, String defaultValue) {
try {
Class> clz = Class.forName("android.os.SystemProperties");
Method get = clz.getMethod("get", String.class, String.class);
return (String)get.invoke(clz, key, defaultValue);
} catch (Exception e) {
}
return defaultValue;
}
}
其中 StatusbarColorUtils类可以在魅族开发者官网可以下载。
本篇文章主要介绍了ToolBar的封装,改变状态栏颜色,其中改变状态栏字体颜色限制较多。可能有的机型会不适配。下一章我们继续介绍在状态栏,状态栏在Fragment中动态改变和如何把布局延伸到状态栏中。