必威体育Betway必威体育官网
当前位置:首页 > IT技术

沉浸式状态栏

时间:2019-10-05 19:43:27来源:IT技术作者:seo实验室小编阅读:52次「手机版」
 

状态栏

如果你觉的原生的费事 请移步 https://github.com/gyf-dev/ImmersionBar 

一个优秀的开源库 低耦合 试用于所有项目 

1、至于为什么叫沉浸式状态栏可以看这里 为什么在国内会有很多用户把「透明栏」(Translucent Bars)称作 「沉浸式顶栏」?(我发觉基本上每篇说statUSBar都会有我自己也传送了;哈哈)

2、沉浸式状态栏仅适用于 4.4以上系统;而4.4至5.0 到 5.0以上这里又分情况

安卓系统上的系统元素

Paste_Image.png

将状态栏和ActionBar隐藏

public class MainActivity extends APPCompatActivity {
    @Override
    protected void onCreate(Bundle savedinstanceState) {
        super.onCreate(savedInstanceState);
        setcontentView(R.layout.activity_main);
        View decorView = getWindow().getDecorView();
        int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
        //设置系统UI元素的可见性。其中,SYSTEM_UI_FLAG_FULLSCREEN表示全屏的意思,也就是会将状态栏隐藏。
        decorView.setSystemUiVisibility(option);
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
                //将actionBar隐藏
                actionBar.hide();
        }
    }
}

上面代码效果如下图:

Paste_Image.png

将状态栏透明

//5.0及以上系统才支持
if(build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            View decorView = getWindow().getDecorView();
//两个Flag必须要结合在一起使用,表示会让应用的主体内容占用系统状态栏的空间
    int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
    decorView.setSystemUiVisibility(option);
//将状态栏设置成透明色
    getWindow().setStatusBarcolor(Color.TRANSparent);
}
ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
                //将actionBar隐藏
                actionBar.hide();
        }

效果:

Paste_Image.png

这里有个问题就是我们的应用如果有标题栏(或toolbar);标题栏就会被系统的状态栏遮盖着一部分。

如下图:

Paste_Image.png

标题栏一部分与状态栏重叠了。解决方法其实就是:

fitsSystemwindows="true"

给 ContentView 的下的ViewGroup设置使其为系统 View 预留空间.

setFitsSystemWindows属性

void setFitsSystemWindows (boolean fitSystemWindows)

Sets whether or not this view should account for system screen decorations such as the status bar and inset its content; that is, controlling whether the default implementation of fitSystemWindows(Rect) will be executed. See that method for more details.

Note that if you are providing your own implementation of fitSystemWindows(Rect), then there is no need to set this flag to true -- your implementation will be overriding the default implementation that checks this flag.

大概意思是:setFitsSystemWindows用来设置影响系统的工具栏如状态栏,决定了这个view是否插入到它的ContentView。当您设置了fitSystemWindows(Rect)而没有将setFitsSystemWindows设置为true,你对fitSystemWindows(Rect)设置是无效的.

该属性可以设置是否为系统 View 预留出空间,当设置为 true 时,会预留出状态栏的空间。

另外一种方式设置透明状态栏

 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            //需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色
            activity.getWindow().addFlags(WindowManager.layoutparams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //状态栏透明颜色
            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
        }
//为了设置全屏
ViewGroup mContentView = (ViewGroup) activity.findViewById(Android.R.id.content);
View mChildView = mContentView.getChildAt(0);
if (mChildView != null) {
    //注意不是设置 ContentView 的 FitsSystemWindows, 而是设置 ContentView 的第一个子 View . 使其不为系统 View 预留空间.
    ViewCompat.setFitsSystemWindows(mChildView, true);
}

注意最后那行代码:

ViewCompat.setFitsSystemWindows(mChildView, true);

这里等同刚刚说的 setFitsSystemWindows(true);,只不过上面的作向下兼容

true 时,会预留出状态栏的空间。切记!切记!切记!

其实如果你的布局是整个图片的话就不需要true了。false也可以,true主要系为了那些有标题栏的布局。防止状态栏与标题栏部分重叠。

贴贴鸿祥大神写的提示

Paste_Image.png

如果我们的布局背景颜色是白色,可以这样解决

View decorView = getWindow().getDecorView();
         //重点:SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 
        int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | 
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 
        decorView.setSystemUiVisibility(option); 
        getWindow().setStatusBarColor(Color.TRANSPARENT);

Paste_Image.png

最后总结几点

  • 对于是图片作为背景的全屏模式,且没有标题栏的情况下。不需要设置setFitsSystemWindows这个属性。
  • 图片作为背景的全屏模式,且有标题栏的情况下。setFitsSystemWindows(false);意思是不给状态栏预留空间。

    和setClipToPadding(true);意思是可以通过padding绘制其他view

  • 非图片为背景,且有标题栏的情况下。setFitsSystemWindows(true);

以上都是基于5.0以上如何使状态栏透明效果。

4.4至5.0之间解决

其实就是通过添加一个同状态栏高度的view,再设置状态栏背景颜色解决

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
            //5.0 - 4.4之间
            //设置状态栏透明属性
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            ViewGroup decorView = (ViewGroup)activity.getWindow().getDecorView();
            int count = decorView.getChildCount();
            //生成一个状态栏大小的矩形,且添加到布局中
            if(count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView){
                //看decorView最后一个是否是StatusBarView
                decorView.getChildAt(count - 1).setbackgroundcolor(color);
            } else {
                StatusBarView statusBarView = createStatusBarView(activity,color,statusBarAlpha);
                //将statusBarView添加到decorView最后;由于decorView是FrameLayout,所以statusBarView放在最顶部
                decorView.addView(statusBarView);
            }
        }

/**
     * 生成一个和状态栏大小相同的半透明矩形条
     * @param activity 需要设置的activity
     * @param color    状态栏颜色值
     * @param alpha    透明值
     * @return 状态栏矩形条
     */
private static StatusBarView createStatusBarView(Activity activity,@ColorInt int color,int alpha){
        //绘制一个和状态栏一样高的矩形 StatusBarView 本质上就是一个View而已;什么属性也没有
        StatusBarView statusBarView = new StatusBarView(activity);
        //宽是MATCH_PARENT,高度就是状态栏的高度
        LinearLayout.LayoutParams params =
                new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,getStatusBarHeight(activity));
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(color);
        return statusBarView;
    }

编辑状态时,状态栏问题:

当用到沉浸式状态栏时,如果界面有编辑栏的时候:

郭霖推荐的博文帮到你

我这里截取方法五的重要部分:

Paste_Image.png

Paste_Image.png

Paste_Image.png

实现步骤:

1、把SoftHideKeyBoardUtil类复制到项目中;

2、在需要使用的Activity的onCreate方法中添加:SoftHideKeyBoardUtil.assistActivity(this);即可。

/**
 * 解决键盘档住输入框
 * Created by SmileXie on 2017/4/3.
 */

public class SoftHideKeyBoardUtil {
    public static void assistActivity (Activity activity) {
        new SoftHideKeyBoardUtil(activity);
    }
    private View mChildOfContent;
    private int usableHeightprevious;
    private FrameLayout.LayoutParams frameLayoutParams;
    //为适应华为小米手机键盘上方出现黑条或不适配
    private int contentHeight;//获取setContentView本来view的高度
    private boolean isfirst = true;//只用获取一次
    private  int statusBarHeight;//状态栏高度
    private SoftHideKeyBoardUtil(Activity activity) {
   //1、找到Activity的最外层布局控件,它其实是一个DecorView,它所用的控件就是FrameLayout
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        //2、获取到setContentView放进去的View
        mChildOfContent = content.getChildAt(0);
        //3、给Activity的xml布局设置View树监听,当布局有变化,如键盘弹出或收起时,都会回调此监听  
          mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        //4、软键盘弹起会使GlobalLayout发生变化
            public void onGlobalLayout() {
            if (isfirst) {
                    contentHeight = mChildOfContent.getHeight();//兼容华为等机型
                    isfirst = false;
                }
                //5、当前布局发生变化时,对Activity的xml布局进行重绘
                possiblyResizeChildOfContent();
            }
        });
        //6、获取到Activity的xml布局的放置参数
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
    }

    // 获取界面可用高度,如果软键盘弹起后,Activity的xml布局可用高度需要减去键盘高度  
    private void possiblyResizeChildOfContent() {
        //1、获取当前界面可用高度,键盘弹起后,当前界面可用布局会减少键盘的高度
        int usableHeightNow = computeUsableHeight();
        //2、如果当前可用高度和原始值不一样
        if (usableHeightNow != usableHeightPrevious) {
            //3、获取Activity中xml中布局在当前界面显示的高度
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            //4、Activity中xml布局的高度-当前可用高度
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            //5、高度差大于屏幕1/4时,说明键盘弹出
            if (heightDifference > (usableHeightSansKeyboard/4)) {
                // 6、键盘弹出了,Activity的xml布局高度应当减去键盘高度
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
                    frameLayoutParams.height = usableHeightSansKeyboard - heightDifference + statusBarHeight;
                } else {
                    frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
                }
            } else {
                frameLayoutParams.height = contentHeight;
            }
            //7、 重绘Activity的xml布局
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }
    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibledisplayFrame(r);
        // 全屏模式下:直接返回r.bottom,r.top其实是状态栏的高度
        return (r.bottom - r.top);
    }
}

(自己记录的属性可以忽略)

在Manifest文件的每个Activity都可设置如下图:

Manifest下Activity标签

真正的沉浸式模式

只有在Android 4.4及以上系统才支持沉浸式模式

重写Activity的onWindowFocusChanged()方法

public class MainActivity extends AppCompatActivity {

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

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_navigation
//SYSTEM_UI_FLAG_LAYOUT_STABLE与SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN结合在一起使用,表示会让应用的主体内容占用系统状态栏的空间
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
//全屏的意思,也就是会将状态栏隐藏
                | View.SYSTEM_UI_FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        }
    }
}

界面默认情况下是全屏的,状态栏和导航栏都不会显示。当我们需要用到状态栏或导航栏时,只需要在屏幕顶部向下拉,或者在屏幕右侧向左拉,状态栏和导航栏就会显示出来,此时界面上任何元素的显示或大小都不会受影响。过一段时间后如果没有任何操作,状态栏和导航栏又会自动隐藏起来,重新回到全屏状态。

Paste_Image.png

隐藏导航栏

View decorView = getWindow().getDecorView();
//将状态栏和导航栏同时隐藏了
int option = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
        | View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(option);
ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
                //将actionBar隐藏
                actionBar.hide();
        }

看上去好像终于是完全全屏化,但其实在这种模式下,触摸屏幕的任意位置都会退出全屏。

效果如图:

Paste_Image.png

实现透明状态栏和导航栏

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    View decorView = getWindow().getDecorView();
//SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,表示会让应用的主体内容占用系统导航栏的空间
    int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
    decorView.setSystemUiVisibility(option);
//setNavigationBarColor()方法将导航栏设置成透明色
    getWindow().setNavigationBarColor(Color.TRANSPARENT);
    getWindow().setStatusBarColor(Color.TRANSPARENT);
}
ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
                //将actionBar隐藏
                actionBar.hide();
        }

效果:

Paste_Image.png

相关阅读

什么是沉浸式设计?它有什么具体特点?

问题:在看《iPhone 人机界面指南》时经常出现一个词:“沉浸式程序” 。最近一些关于 Windows 8 的报道也有“沉浸式”这个词(Windows

Android 沉浸式状态栏完美解决方案

注明下,这里只讲状态栏,导航栏后面看有没有必要再讲国内很多类似的文章, 我只想说一个字, 真tm乱! 我看不懂… 评论里面 全在

电脑打字的时候输入法不显示状态栏怎么办?

有时我们在打字的时候,输入法不显示,能打出汉字,但无法选字,这就给输入字体造成了很大的麻烦。怎么解决呢?下面以搜狗输入法为例,描述详

在IE浏览器状态栏中显示“网页上有错误错误”的几个原

在浏览网站时,多数网友都曾经碰到过这种情况,打开的网页下方IE浏览器状态栏中显示“网页上有错误”,虽然并不影响文字阅读

分享到:

栏目导航

推荐阅读

热门阅读