[奇技淫巧] Android 4.4 5.0 6.0 另一种思路的沉浸式状态栏
最近在写公司项目
想统一写一下沉浸式状态栏,看到网上的例子,感觉还是好复杂啊,,Ծ‸Ծ,,
要配置xml,一会又要写代码 有些地方也不一定会用到,又要去配置一遍,有没有什么简单点,在一处配置,简便使用的方法呢?
所以想到了一个简单的奇技淫巧来达到目的
思路
我们只需要考虑用不同版本的方法把默认的状态栏全部隐藏掉,在基类中创建一个空白View填满原本是状态栏的位置,我们只需要控制好自己创建的statusBar就可以了,这样就不会有各种各样麻烦的东西出现,简化很多很多。
创建基类BaseActivity
/**
* Created by HuangQS on 2017/6/22 04:33
* Email:515215310@qq.com
*/
public abstract class BaseActivity extends AppCompatActivity{
protected boolean isShowStatusBar = true; //设置是否显示伪造的状态栏
protected int statusColor = -1; //状态栏颜色
protected abstract int setLayoutResId(); //资源文件位置 回传R.layout.activity_main
protected abstract void initView(); //初始化控件
protected abstract void initListener(); //初始化监听器
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int resId = setLayoutResId();
mContext = this;
try {
if (resId > 0) {
setContentView(R.layout.activity_base);
View statusBar = findViewById(R.id.view_base_status_bar);
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.fl_base_content);
LayoutInflater.from(mContext).inflate(resId, frameLayout, true);
initView();
initListener();
//设置状态栏
//注意状态栏的位置一定要在initView的后面
//我们会在继承BaseActivity的activity里initView()中设置颜色和显示状态栏
NewStatusBarUtils.setStatusBarUtils(this, isShowStatusBar, statusBar, statusColor);
}
} catch (Exception e) {
//如果错误应该没有错误
e.printStackTrace();
}
}
}
基类里面具体放什么,就随便你啦,反正基本的就这些
然后是上面出现的activity_base的代码 很简单 就只是一个控件(伪状态栏)和一个存放子类Activity的ViewGroup
基类的布局
<?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">
<!--伪造的状态栏-->
<View
android:id="@+id/view_base_status_bar"
android:layout_width="match_parent"
android:layout_height="40dp"
android:visibility="gone"/>
<!--内容布局 子类activity中的内容都会在这里-->
<FrameLayout
android:id="@+id/fl_base_content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
写完这些,接下来就是工具类NewStatusBarUtils 为了方便,就把包名也写进来吧。这样复制的时候,就不会出问题了(一般也不会出问题的= = )
状态栏工具类NewStatusBarUtils
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v4.app.ActivityCompat;
import android.support.v4.view.ViewCompat;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
/**
* 状态栏工具类
* Created by HuangQS on 2017/6/22 09:20
* Email:515215310@qq.com
*/
public class NewStatusBarUtils {
private static final int INVALID_VAL = -1;
private static final int COLOR_DEFAULT = Color.GREEN;
public static void setStatusBarUtils(Activity activity, boolean isShow, View statusBar) {
setStatusBarUtils(activity, isShow, statusBar, INVALID_VAL);
}
public static void setStatusBarUtils(Activity activity, boolean isShow, View statusBar, int statusColor) {
//设置状态栏默认颜色
if (isShow) {
if (statusColor == INVALID_VAL) {
statusColor = ActivityCompat.getColor(activity, R.color.status_bar_color);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //version_code > 5.0
setHideStatusBar21(activity);
if (isShow) {
ViewGroup.LayoutParams layoutParams = statusBar.getLayoutParams();
layoutParams.height = getStatusBarHeight(activity);
statusBar.setVisibility(View.VISIBLE);
statusBar.setBackgroundColor(statusColor);
} else {
statusBar.setVisibility(View.GONE);
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { //4.4 <= version_code<5.0
setHideStatusBar19(activity);
if (isShow) {
ViewGroup.LayoutParams layoutParams = statusBar.getLayoutParams();
layoutParams.height = getStatusBarHeight(activity);
statusBar.setVisibility(View.VISIBLE);
statusBar.setBackgroundColor(statusColor);
} else {
statusBar.setVisibility(View.GONE);
}
} else {
LogUtils.d(NewStatusBarUtils.class.getSimpleName(), ":setStatusBarUtils 4.4以下");
}
}
//4.4~~5.0隐藏状态栏
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private static void setHideStatusBar19(Activity activity) {
Window window = activity.getWindow();
window.setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
// StatusBarHelper.from(activity).setTransparentStatusbar(true).process();
WindowManager.LayoutParams winParams = window.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
winParams.flags |= bits;
window.setAttributes(winParams);
}
//5.0++隐藏状态栏
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private static void setHideStatusBar21(Activity activity) { //隐藏5.0++状态栏
Window window = activity.getWindow();
window.setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
activity.getWindow().setNavigationBarColor(Color.TRANSPARENT);
if (AndroidWorkaround.checkDeviceHasNavigationBar(activity)) {
AndroidWorkaround.assistActivity(activity.findViewById(android.R.id.content));
}
}
//获取状态栏高度,网上的教程很多都是这个方法一模一样= = 果然天下代码一大抄 哈哈哈
private static int getStatusBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
}
Activity子类中的控制
public class LoginFragment extends BaseActivity{
@Override
public void initView() {
isShowStatusBar = true; //显示状态栏,基类中是true,此处为了演示方便临时写一下意思意思而已,别介意
statusColor = ActivityCompat.getColor(activity, R.color.status_bar_color);
//这些都是不重要的东东了 可以不用理 关键的都在上面↑↑↑
scrollView = $findViewById(R.id.sv_fragment_login_scroll);
etUserName = $findViewById(R.id.login_et_username);
etPassword = $findViewById(R.id.login_et_password);
tvForgetPwd = $findViewById(R.id.login_tv_forget_pwd);
btnLogin = $findViewById(R.id.login_btn_login);
btnRegister = $findViewById(R.id.login_btn_register);
}
@Override
protected void initListener() {
//实现监听器
}
@Override
public int setLayoutResId() {
return R.layout.fragment_login; //在这里设置布局,在基类中自动处理。
}
}
所有的代码已经简化到非常简单,代码也比较清晰(我自己这么认为的, (。˘•ε•˘。)别打我)大概就是这些关键点。
不过有一个需要说明的这种方法很快捷的管理实现状态栏,可以对状态栏颜色,状态栏显示隐藏做控制,但是有一点需要知道,那就是:
在基类中多出一层layout界面,如果代码追求极度简洁,强迫癌终极患者,可能会影响到性能(。・`ω´・)
其他快捷介绍 Level > 5.0++
透明隐藏顶部状态栏(也就是顶部电池,时间,信号的条条)Translucent status bar
window.setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
透明隐藏底部导航栏 (也就是底部的虚拟按键) Translucent navigation bar
window.setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
设置状态栏背景颜色
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
设置底部虚拟按键背景颜色
activity.getWindow().setNavigationBarColor(Color.BLUE);
相关资料
华为虚拟按键导致导航栏顶上去的解决方法[链接]
实现4.4以上的状态栏变色,参考这里的StatusBarUtils 对顶部状态栏处理 测试发现该方法在华为Nova 7.0貌似没有效果,所以只作为参考[链接]