Android实现沉浸式状态栏效果

关于沉浸式状态栏,给大家推荐一个非常好的博文android标题栏、状态栏图标文字颜色及背景动态变化

另外说明下,沉浸式状态栏的实现仅适用于 android 4.4及以上版本,4.4以下的就不要想了。

1. 实现秀明状态栏常规方法

    //是否使用特殊的标题栏背景颜色,android5.0以上可以设置状态栏背景色,如果不使用则使用透明色值
    protected boolean useThemestatusBarColor = false;
    //是否使用状态栏文字和图标为暗色,如果状态栏采用了白色系,则需要使状态栏和图标为暗色,android6.0以上可以设置
    protected boolean useStatusBarColor = true;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setStatusBar();
    }

      protected void setStatusBar() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0及以上
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            //根据上面设置是否对状态栏单独设置颜色
            if (useThemestatusBarColor) {
                getWindow().setStatusBarColor(getResources().getColor(R.color.colorTheme));//设置状态栏背景色
            } else {
                getWindow().setStatusBarColor(Color.TRANSPARENT);//透明
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4到5.0
            WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
            localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
        } else {
            Toast.makeText(this, "低于4.4的android系统版本不存在沉浸式状态栏", Toast.LENGTH_SHORT).show();
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && useStatusBarColor) {//android6.0以后可以对状态栏文字颜色和图标进行修改
            getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        }
    }

在Activity布局的根节点处加上android:fitsSystemWindows=”true”属性就可以了,要不布局会跑到状态栏和导航栏下面,与导航栏和状态栏重叠,这当然不是我们希望的。

效果图如下:
这里写图片描述

此时,
useThemestatusBarColor = false,说明不设置状态栏背景色,为透明
useStatusBarColor = true,使状态栏图标和文字变暗,这个很有必要,不设置为true的话,由于状态栏字体颜色为白色,和状态栏背景色重叠,分不清。

上面设置状态栏文字颜色和图标为暗色主要采用了以下两个标志:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && useStatusBarColor) {//android6.0以后可以对状态栏文字颜色和图标进行修改
            getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        }

2. 同一个Activity包含多个Fragment时,如何实现不同fragment的状态栏背景和文字颜色不一样
实现以下效果
(1).当标题栏背景为图片时,此时需要背景图片填充到状态栏的效果,如左图
(2).当标题栏背景不是图片,此时不需要背景图片填充状态栏的效果,如右图
暂时不考虑标题栏中既有背景图,又有背景色的情况,当然也可以实现,将左图中的标题栏的高度设置高一点即可(右图中的状态栏背景既有图片又有背景色仅仅是为了显示区分)
图1 图2

就是设置了状态栏为暗色后,还得设置回来,这其实主要靠下面两个flag标识,结全上面的两个flag标识就能实现。

//设置状态栏文字颜色及图标为浅色
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
  • View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 前面说过了,是为了让视图能延伸到状态栏区域,使状态栏悬浮在视图布局之上。

  • View.SYSTEM_UI_FLAG_LAYOUT_STABLE
    保持整个View稳定, 常和控制System UI悬浮, 隐藏的Flags共用, 使View不会因为System UI的变化而重新layout。

贴出MainActivity中的代码:

public class MainActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener,
        ViewPager.OnPageChangeListener {
    private static final String TAG = "MainActivity";

    public static final int PAGE_ONE = 0;
    public static final int PAGE_TWO = 1;
    public static final int PAGE_THREE = 2;
    public static final int PAGE_FOUR = 3;


    private RadioGroup rgTabBar;
    private RadioButton rbChannel;
    private RadioButton rbMessage;
    private RadioButton rbBetter;
    private RadioButton rbSetting;
    private ViewPager viewpager;
    private MyFragmentPagerAdapter mAdapter;

    //是否使用特殊的标题栏背景颜色,android5.0以上可以设置状态栏背景色,如果不使用则使用透明色值
    protected boolean useThemestatusBarColor = true;
    //是否使用状态栏文字和图标为暗色,如果状态栏采用了白色系,则需要使状态栏和图标为暗色,android6.0以上可以设置
    protected boolean useStatusBarColor = true;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
        initViews();
    }

    private void initViews() {

        rgTabBar = findViewById(R.id.rg_tab_bar);
        rbChannel = findViewById(R.id.rb_channel);
        rbMessage = findViewById(R.id.rb_message);
        rbBetter = findViewById(R.id.rb_better);
        rbSetting = findViewById(R.id.rb_setting);
        viewpager = findViewById(R.id.viewpager);

        rgTabBar.setOnCheckedChangeListener(this);
        viewpager.setAdapter(mAdapter);
        viewpager.setCurrentItem(0);
        viewpager.addOnPageChangeListener(this);
        rbChannel.setChecked(true);

    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        switch (checkedId) {
            case R.id.rb_channel:
                viewpager.setCurrentItem(PAGE_ONE);

                setStatusBar(R.color.colorWhite);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//build.gradle中compileSdkVersion>=23
                //    实现状态栏图标和文字颜色为暗色
                    getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                }
                break;
            case R.id.rb_message:
                viewpager.setCurrentItem(PAGE_TWO);

                setStatusBar(R.color.colorRed);
                getWindow().getDecorView().setSystemUiVisibility(
                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);

                break;
            case R.id.rb_better:

                setStatusBar(R.color.colorGreen);
                getWindow().getDecorView().setSystemUiVisibility(
                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
                break;
            case R.id.rb_setting:
                viewpager.setCurrentItem(PAGE_FOUR);

                setStatusBar(R.color.colorBlue);
                getWindow().getDecorView().setSystemUiVisibility(
                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
                break;
        }
    }


    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == ViewPager.SCROLL_STATE_SETTING) {
            int currentItemPosition = viewpager.getCurrentItem();
            Log.w(TAG, "onPageScrollStateChanged: currentItemPosition::" + currentItemPosition);
            switch (currentItemPosition) {
                case PAGE_ONE:
                    rbChannel.setChecked(true);
                    break;
                case PAGE_TWO:
                    rbMessage.setChecked(true);
                    break;
                case PAGE_THREE:
                    rbBetter.setChecked(true);
                    break;
                case PAGE_FOUR:
                    rbSetting.setChecked(true);
                    break;
            }
        }
    }

    //******************************************************************************************
    protected void setStatusBar(int colorId) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0及以上
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            //根据上面设置是否对状态栏单独设置颜色
            if (useThemestatusBarColor) {
                getWindow().setStatusBarColor(getResources().getColor(colorId));//设置状态栏背景色
            } else {
                getWindow().setStatusBarColor(Color.TRANSPARENT);//透明
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4到5.0
            WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
            localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
        } else {
            Toast.makeText(this, "低于4.4的android系统版本不存在沉浸式状态栏", Toast.LENGTH_SHORT).show();
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && useStatusBarColor) {//android6.0以后可以对状态栏文字颜色和图标进行修改
            getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        }
    }

}

另外特别强调下
上述代码暂时不适用于底部带有导航栏的手机,如果对上述代码不做处理的话那么,带有底部导航栏手机底部导航按钮会和navigationbar重叠。
如过你的手机底部带有导航栏的话,还是强烈推荐你看那篇非常好的博文android标题栏、状态栏图标文字颜色及背景动态变化
好了,上述内容就是我记录的对于“沉浸式状态栏”的认识,也是为了加深理解和掌握其用法。对于不含底部带有导航栏的手机上述代码足够实现常用的沉浸式效果了。

后续待我会继续参照大牛的博客,完善此篇文章。小伙伴如果有疑问的话,请留言,我们共同学习!!!

猜你喜欢

转载自blog.csdn.net/zhangqunshuai/article/details/80582719