美文网首页Android之界面Android技术知识Android开发
快速实现沉浸式状态栏,沉浸式,你复制这篇代码就够用了!

快速实现沉浸式状态栏,沉浸式,你复制这篇代码就够用了!

作者: walle9 | 来源:发表于2018-04-28 11:12 被阅读461次

关于沉浸式的定义,这里不作争论...

透明状态栏,透明导航栏

通过主题配置

styles.xml

<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"/>
    
</resources>

res下新建values-v19,values-v21文件夹

values-v19下添加styles.xml

<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- 表示状态栏透明,并且会使得状态栏悬浮在activity之上(activity布局会扩展到状态栏底部) -->
        <item name="android:windowTranslucentStatus">true</item>
        <!-- 表示导航栏半透明,并且会使得状态栏和导航栏都悬浮在activity之上 -->
        <item name="android:windowTranslucentNavigation">true</item>
    </style>

</resources>

values-v21下添加styles.xml

<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- 表示状态栏透明,并且会使得状态栏悬浮在activity之上(activity布局会扩展到状态栏底部) -->
        <item name="android:windowTranslucentStatus">false</item>
        <!-- 表示导航栏半透明,并且会使得状态栏和导航栏都悬浮在activity之上 -->
        <item name="android:windowTranslucentNavigation">true</item>
        <!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的颜色-->
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>

</resources>

OK,我们看下我们的布局,然后看效果,布局随便写的,就是一个ScrollView套了一张图而已

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#1478d5"
            android:orientation="vertical">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/a"/>

        </LinearLayout>

    </ScrollView>

</LinearLayout>
16a01313-a35f-4878-a67e-a7f210feb8e9.jpg

下面我们看下效果:


afd915cc-8edb-40c4-b23d-574ce8d8f426.jpg

[========]

使用代码实现

当然,记得styles.xml保留下NoActionBar

<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"/>

</resources>

    protected void initBar() {
        
        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_HIDE_NAVIGATION    //标志布局会侵入到导航栏下
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;            //保持稳定
            decorView.setSystemUiVisibility(option);                //设置系统UI可见属性

            getWindow().setStatusBarColor(Color.TRANSPARENT);       //设置状态栏颜色透明
            getWindow().setNavigationBarColor(Color.TRANSPARENT);   //设置导航栏颜色透明
            
            //设置状态栏为半透明
            //getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //设置导航栏为半透明
            //getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

        } 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);
        }
        
    }

效果如下:


9712d183-a7e9-48af-8f29-931497dd88f1.jpg

附赠:窗口的层级的经典图片

2dd9d60f-d3ec-448e-ad0d-6b7545d7a8e6.jpg

当然,你也可以设置导航栏为别的颜色
例如:

            getWindow().setStatusBarColor(Color.parseColor("#581478d5"));       //设置状态栏颜色
            getWindow().setNavigationBarColor(Color.parseColor("#581478d5"));   //设置导航栏颜色
67eeb26c-288d-4be5-90ff-6e9c322416a9.jpg

或者你把这两句代码去掉,直接设置或者在主题编辑器中修改

31efaed5-8aff-40f9-b796-49cf0ad4b08a.jpg
af4a3412-9848-4142-9bd7-cf62c58a9216.png
8011c522-4876-40cc-85a9-cb67b2971df9.png

效果如下:


880fba6c-44d5-4e6b-8425-36bc9b88436a.jpg

附赠另一张经典图片:

c1f94172-5565-4d03-80a6-2a43c1e89978.jpg

[========]

有时候我们不想让布局中的内容也侵入到状态栏怎么办呢?
加个margin或padding呗!

3ad656d9-c091-48ea-9ac5-9d84acfb8305.png

效果如下:


GIFa.gif

等等walle9,我的特么的为什么是白乎乎的?

哈哈,难道你没看到我早已在LinearLayout上添加了一个颜色?...

可是我还有个问题,我就想让magin的值跟状态栏的高度一样怎么做呀?

嗯!写成30试试....或者代码中算一下高度呗!

其实我们还可以使用android:fitsSystemWindows这个属性来设置.


fitsSystemWindows只作用在sdk>=19的系统上就是高于4.4的系统
这个属性可以给任何view设置,只要设置了这个属性此view的所有padding属性失效.

只有在设置了透明状态栏(StatusBar)或者导航栏(NavigationBar)此属性才会生效
同时,所有设置了android:fitsSystemWindows=”true”属性的view会自动添加一个值等于状态栏高度的paddingTop,会自动添加一个值等于导航栏高度的paddingBottom

来呗!试一下!

e913da09-c16a-496a-9c1c-0d3a557c482e.png 0429ea57-4e1c-4072-a134-4b8b70519723.jpg

顶出来了,有木有!

日了狗了!你又骗老子!

骚年啊!我没有骗你啊!下面的margin咱们忘记去掉了不是么!再试一下好咯!

bfb43129-ab04-4c9a-8254-a5866251c88f.png 75445770-1892-465b-96be-2bfc73974715.jpg

恩恩!这次一样大了!


听说使用android:fitsSystemWindows="true"这个属性的view中的padding值会失效,咱们试试呗!

先试padding值:


2c1a4570-a4b5-4519-92c1-f8688a9715ba.png

效果如下:


47424171-3fe1-4d7e-96b7-0767b9562e63.jpg

加上android:fitsSystemWindows="true"

a735eed0-a46a-4d0f-b805-0286192db2c8.png

效果如下:


59e01256-491a-404e-812b-4a052cf096b1.jpg

但是,需要注意哦,在我们滑动到最底部的时候,底部导航也会出现一个padding值,如果你介意的话,那就用magin或padding来设置.写个相近值或者代码中计算具体值.

cad549a9-5ea2-44df-9a55-0a5a4f4df19c.jpg

下面我们在代码中计算:
没啥好说的,先设置一个id....


6f062734-eda1-4481-8866-99b4fbfe977e.png

当然,你愿意在最外层那个linearlayout上面设置也可以,你高兴就好!

代码中找到这个控件,计算出状态栏的高度,设置padding...

    private void initStatusBar() {
        int statusBarHeight = getStatusBarHeight();
        LinearLayout ll =findViewById(R.id.ll);
        ll.setPadding(0,statusBarHeight,0,0);
    }

获取状态栏高度:

    private int getStatusBarHeight() {
        int result = 0;
        int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resId > 0) {
            result = getResources().getDimensionPixelSize(resId);
        }
        return result;
    }

再次附赠:获取导航栏高度

    public float getNavigationBarHeight() {
        float result = 0;
        int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = getResources().getDimension(resourceId);
        }
        return result;
    }

效果如下:


cb256216-7df2-4c57-9e9f-4ef1ef718291.jpg

[========]

沉浸式

并不是所有的手机都像华为那样自带隐藏虚拟导航键的功能,虚拟导航键挡住了布局的底部导航怎么办呢?

骚年!看这里!自动隐藏导航...

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus && Build.VERSION.SDK_INT >= 19) {
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY        //粘性沉浸体验
                    |View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION //布局侵入导航
                    |View.SYSTEM_UI_FLAG_HIDE_NAVIGATION        //隐藏导航
                    //|View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN      //全屏标记,布局侵入
                    //|View.SYSTEM_UI_FLAG_FULLSCREEN             //隐藏状态栏
                    |View.SYSTEM_UI_FLAG_LAYOUT_STABLE          //保持稳定
            );
        }
    }

效果如下:


GIFb.gif

自动隐藏状态栏:

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus && Build.VERSION.SDK_INT >= 19) {
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY        //粘性沉浸体验
                            |View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION //布局侵入导航
                            //|View.SYSTEM_UI_FLAG_HIDE_NAVIGATION        //隐藏导航
                            |View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN      //全屏标记,布局侵入
                            |View.SYSTEM_UI_FLAG_FULLSCREEN             //隐藏状态栏
                            |View.SYSTEM_UI_FLAG_LAYOUT_STABLE          //保持稳定
            );
        }
    }

效果如下:


GIFc.gif

机智的你早已放开了一切...
那么恭喜你,你学会了沉浸式...

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus && Build.VERSION.SDK_INT >= 19) {
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY        //粘性沉浸体验
                            |View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION //布局侵入导航
                            |View.SYSTEM_UI_FLAG_HIDE_NAVIGATION        //隐藏导航
                            |View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN      //全屏标记,布局侵入
                            |View.SYSTEM_UI_FLAG_FULLSCREEN             //隐藏状态栏
                            |View.SYSTEM_UI_FLAG_LAYOUT_STABLE          //保持稳定
            );
        }
    }

效果如下:


GIFd.gif

over...
上传图片不容易,且复制且珍惜吧!

相关文章

网友评论

    本文标题:快速实现沉浸式状态栏,沉浸式,你复制这篇代码就够用了!

    本文链接:https://www.haomeiwen.com/subject/jcnwlftx.html