Android沉溺模式

什么是沉溺模式?

我们理解的沉溺模式都是指状态栏和ActionBar一样的颜色,但其实在设计师那边并不是这个意思,我们这里讨论就按我们曲解的意思讨论吧。

有什么难度

沉溺模式其实一开始是从iOS那边过来的,Android上实现沉溺模式并没有那么简单,Android Kitkat才开始可以在状态栏下面放内容,Lollipop 才支持真正意义上的修改状态连颜色。
但是可悲的是KitKat目前是市场上占有率最高的系统,如果media/不是在Kitkat这个版本上实现并没有什么意义.

实现方式

要想在KitKat上实现改变系统状态栏颜色是不可能的,我们只能通过曲线救国的方式来实现。KitKat上支持一种模式,把内容放到StateBar下面,我们通过这种方式来实现改变状态栏颜色的功能,但是这个方法有几个弊端。第一,原生的Android系统,StateBar是有渐变黑色的,这个无法去掉。第二,开启这个功能后,需要根部的View 启用fitSystemWindow功能,但是启用这个功能之后,根部View的Padding将不能使用。

问题解决方案

为了对开发者透明,也为了不每次都会麻烦,我们对开启fitSystemWindow 这个功能进行了封装,原理就是在原本的根部View上包裹一个FrameLayout ,然后使用FrameLayout开启fitSystemWindow ,这样开发者就可以想操作平常的页面一样去开发新的页面了。

效果预览

代码实现

package com.hangox.aboutsystembartint;


import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;


import com.readystatesoftware.systembartint.SystemBarTintManager;


/**
 * Created With Android Studio
 * User hangox
 * Date 15/10/20
 * Time 下午9:55
 * 沉溺状态栏助手
 */
public class SystemBarTintHelper {
    private Activity mActivity;
    private SystemBarTintManager mTintManager;


    public SystemBarTintHelper(Activity activity) {
        mActivity = activity;
        setUpTranslucentStatus();//开启透明状态栏
        mTintManager = new SystemBarTintManager(mActivity);
    }


    /**
     * 开启调用
     */
    public void setUp(int color) {
        mTintManager.setStatusBarTintEnabled(true);
        mTintManager.setStatusBarTintColor(color);
    }




    /**
     * 使用代码启动透明状态栏
     */
    @TargetApi(19)
    private void setUpTranslucentStatus() {
        Window win = mActivity.getWindow();
        WindowManager.LayoutParams winParams = win.getAttributes();
        final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
        winParams.flags |= bits;
        win.setAttributes(winParams);
    }


    /**
     * 因为如果根部View设置fitSystemWindow = true 后,padding 就会无效,
     * 做不到对开发者透明,所以只能在原本的根部View套上一个FrameLayout
     * 再对FrameLayout 执行isFitSystem = true这样就不会影响原来的布局
     */
    public void handleViewAfterSetContent() {
        ViewGroup decorView = (ViewGroup) mActivity.getWindow().getDecorView().findViewById(android.R.id.content);
        View rootView = decorView.getChildAt(0);
        decorView.removeView(rootView);
        View newRootView = generateNewRootView(rootView, null);
        newRootView.setFitsSystemWindows(true);
        decorView.addView(newRootView);
    }




    /**
     * 生成一个新的根部View
     * @param rootView
     * @param layoutParams
     * @return
     */
    public FrameLayout generateNewRootView(View rootView, ViewGroup.LayoutParams layoutParams){
        FrameLayout frameLayout = new FrameLayout(mActivity);
        if (layoutParams == null) frameLayout.setLayoutParams(rootView.getLayoutParams());
        else frameLayout.setLayoutParams(layoutParams);
        frameLayout.addView(rootView);
        return frameLayout;
    }


    public static boolean isKitKat() {
        return Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT;
    }
}



在Activity 的代码

package com.hangox.aboutsystembartint;


import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;


/**
 * 示范Activity
 */
public class MainActivity extends AppCompatActivity {


    protected SystemBarTintHelper mSystemBarTintHelper ;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //透明状态栏只能再kitkat 以上的版本开启,但是Android5.0 之后提供了primaryDark这种东西更改
        //状态栏模式,所以只要再kitkat 模式上开启就好了
        if (SystemBarTintHelper.isKitKat()) {
            mSystemBarTintHelper = new SystemBarTintHelper(this);
//            mSystemBarTintHelper.setSystemBarColor(getResources().getColor(R.color.colorPrimaryDark));
            mSystemBarTintHelper.setUp(getResources().getColor(R.color.colorPrimaryDark));
        }
        setContentView(R.layout.activity_main);
    }


    @Override
    public void setContentView(int layoutResID) {
        super.setContentView(layoutResID);
        if(SystemBarTintHelper.isKitKat()){
            mSystemBarTintHelper.handleViewAfterSetContent();
        }
    }


    @Override
    public void setContentView(View view) {
        if(SystemBarTintHelper.isKitKat()){
            view = mSystemBarTintHelper.generateNewRootView(view,null);
        }
        super.setContentView(view);
    }


    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        if(SystemBarTintHelper.isKitKat()){
           view =  mSystemBarTintHelper.generateNewRootView(view, params);
        }
        super.setContentView(view, params);
    }
}