文档章节

Android源码笔记--SystemUIVisibility

天王盖地虎626
 天王盖地虎626
发布于 06/18 16:31
字数 726
阅读 12
收藏 0

SystemUIVisibility     

       最近在学习SystemUI时,涉及到了SystemUIVisibility,在此记录一下。虽然StatusBarManager以及StatusBarManagerService为应用程序以及系统服务提供了操作状态栏与导航栏的所有接口,但是这些接口并不适用于那些没有系统签名的普通应用程序。如果普通应用程序希望对状态栏以及导航栏进行操作,就需要使用SystemUIVisibility机制。

    View.java
    //隐藏导航栏
    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
    //隐藏状态栏
    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;

       常见设置SystemUIVisibility的方式有两种。一是在任意一个已经显示在窗口上的控件调用View.setSystemUiVisibility(),二是直接在窗口的LayoutParams.systemUiVisibility上进行设置并通过WindowManager.updateViewLayout()方法使其生效。

       SystemUIVisibility在系统中存在的地方

        SystemUIVisibility主要涉及状态栏和导航栏的行为以及窗口布局两个方面。因此它的消费者包含SystemUI中BaseStatusBar以及负责窗口布局的PhoneWindowManger。

 1  控件树中的SystemUIVisibility

View.setSystemUiVisibility()的实现

        View.java
     
        public void setSystemUiVisibility(int visibility) {
            if (visibility != mSystemUiVisibility) {
               //(1) 保存在View自己的成员变量mSystemUiVisibility.
                mSystemUiVisibility = visibility;
                //(2)通知父控件这一变化
                if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
                    mParent.recomputeViewAttributes(this);
                }
            }
        }

    ViewRootImpl.java
        
          @Override
        public void recomputeViewAttributes(View child) {
       // 需要在窗口的主线程中调用
            checkThread();
            if (mView == child) {
        // 2  标记需要处理SystemUIVisibility的变化
               mAttachInfo.mRecomputeGlobalAttributes = true;
                if (!mWillDrawSoon) {
        // 3 触发一次“遍历”动作
                    scheduleTraversals();
                }
            }
        }

分析:遍历过程中会执行ViewRootImpl.collectViewAttributes()方法收集控件树中每个View所保存的SystemUIVisibility. 如下:

    private boolean collectViewAttributes() {
            if (mAttachInfo.mRecomputeGlobalAttributes) {
                //Log.i(mTag, "Computing view hierarchy attributes!");
                mAttachInfo.mRecomputeGlobalAttributes = false;
                boolean oldScreenOn = mAttachInfo.mKeepScreenOn;
                mAttachInfo.mKeepScreenOn = false;
            //清空所保存的SystemUiVisibility
               mAttachInfo.mSystemUiVisibility = 0;
                mAttachInfo.mHasSystemUiListeners = false;
            //遍历整个控件树
                mView.dispatchCollectViewAttributes(mAttachInfo, 0);
            //移除被禁用的SystemUiVisibility标记    
               mAttachInfo.mSystemUiVisibility &= ~mAttachInfo.mDisabledSystemUiVisibility;
                WindowManager.LayoutParams params = mWindowAttributes;
                mAttachInfo.mSystemUiVisibility |= getImpliedSystemUiVisibility(params);
                if (mAttachInfo.mKeepScreenOn != oldScreenOn
                        || mAttachInfo.mSystemUiVisibility != params.subtreeSystemUiVisibility
                        || mAttachInfo.mHasSystemUiListeners != params.hasSystemUiListeners) {
                    applyKeepScreenOnFlag(params);
            //将SystemUiVisibility保存到窗口的LayoutParams
                   params.subtreeSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
                    params.hasSystemUiListeners = mAttachInfo.mHasSystemUiListeners;
                    mView.dispatchWindowSystemUiVisiblityChanged(mAttachInfo.mSystemUiVisibility);
                    return true;
                }
            }
            return false;
        }

     分析:当ViewRootImpl通过WMS.reLayoutWindow()方法对窗口进行重新布局时,本窗口所期望的SUV会伴随着LayoutParams

.subtreeSystemUiVisibility以及LayoutParams.sytemUiVisibility两个字段进入WMS.

     WindowManagerService.java
     
             public int relayoutWindow(Session session, IWindow client, int seq,
                WindowManager.LayoutParams attrs, int requestedWidth,
                int requestedHeight, int viewVisibility, int flags,
                Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
                Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
                Configuration outConfig, Surface outSurface) {
                
                .................
                
                   synchronized(mWindowMap) {
                WindowState win = windowForClientLocked(session, client, false);
                if (win == null) {
                    return 0;
                }
     
                WindowStateAnimator winAnimator = win.mWinAnimator;
                if (viewVisibility != View.GONE) {
                    win.setRequestedSize(requestedWidth, requestedHeight);
                }
     
                int attrChanges = 0;
                int flagChanges = 0;
                if (attrs != null) {
                    mPolicy.adjustWindowParamsLw(attrs);
                    // if they don't have the permission, mask out the status bar bits
                    if (seq == win.mSeq) {
                        int systemUiVisibility = attrs.systemUiVisibility
                                | attrs.subtreeSystemUiVisibility;
                        if ((systemUiVisibility & DISABLE_MASK) != 0) {
                            if (!hasStatusBarPermission) {
                                systemUiVisibility &= ~DISABLE_MASK;
                            }
                        }
                        //保存到WindowState.mSystemUiVisibility
                        win.mSystemUiVisibility = systemUiVisibility;
                    }
                    if (win.mAttrs.type != attrs.type) {
                        throw new IllegalArgumentException(
                                "Window type can not be changed after the window is added.");
                    }
                
                ........
                }

        在此,PhoneWindowManager可以通过WindowState.getSystemUiVisibility获取这一信息并据此对窗口进行布局,或设置状态栏与导航栏的可见性。
 

本文转载自:https://blog.csdn.net/ljt2724960661/article/details/82779519

天王盖地虎626

天王盖地虎626

粉丝 31
博文 522
码字总数 20708
作品 0
南京
私信 提问
ActionBar的透明和自动隐藏显示

参考文档: http://www.androidcommunitydocs.com/guide/topics/ui/actionbar.html http://www.androidcommunitydocs.com/guide/topics/ui/menus.html 1.定义主题,设置windowActionBarOver......

IamOkay
2015/01/25
3.3K
0
一份关于 Java、Kotlin 与 Android 的学习笔记

JavaKotlinAndroidLearn 这是一份关于 Java 、Kotlin 、Android 的学习笔记,既包含对基础知识点的介绍,也包含对一些重要知识点的源码解析,笔记的大纲如下所示: Java 重拾Java(0)-基础知...

叶应是叶
2018/08/08
0
0
Android--面试中遇到的问题总结(三)

《Android 开发工程师面试指南 LearningNotes 》,作者是陶程,由梁观全贡献部分。大家可以去知乎关注这两位用心的少年。这份指南包含了大部分Android开发的基础、进阶知识,不仅可以帮助准备...

sealin
2017/02/22
0
0
Android应用层源码阅读笔记--Application

Android应用层源码阅读笔记--Application 导言 在这个年头,问到看过android 源码没?必定问的就是你是否看过android linux层的代码,你说没看过,都貌似不好意思说自己学过android的.我就想了,...

打杂程序猿
2012/11/20
291
0
BAT等大厂Android面试书单和知识点清单

java是Android开发的基础,在BAT的初面中,会涉及到比较多的java基础知识,所以比较重要,下面我介绍的书籍内容是由浅到深。 1.Thinking in java:这本书被称为Java的三大圣经之一,虽然书比...

android自学
2018/07/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

redis 学习2

网站 启动 服务端 启动redis 服务端 在redis 安装目录下 src 里面 ./redis-server & 可以指定 配置文件或者端口 客户端 在 redis 的安装目录里面的 src 里面 ./redis-cli 可以指定 指定 连接...

之渊
24分钟前
0
0
Spring boot 静态资源访问

0. 两个配置 spring.mvc.static-path-patternspring.resources.static-locations 1. application中需要先行的两个配置项 1.1 spring.mvc.static-path-pattern 这个配置项是告诉springboo......

moon888
今天
3
0
hash slot(虚拟桶)

在分布式集群中,如何保证相同请求落到相同的机器上,并且后面的集群机器可以尽可能的均分请求,并且当扩容或down机的情况下能对原有集群影响最小。 round robin算法:是把数据mod后直接映射...

李朝强
今天
4
0
Kafka 原理和实战

本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/bV8AhqAjQp4a_iXRfobkCQ 作者简介:郑志彬,毕业于华南理工大学计算机科学与技术(双语班)。先后从事过电子商务、开放平...

vivo互联网技术
今天
21
0
java数据类型

基本类型: 整型:Byte,short,int,long 浮点型:float,double 字符型:char 布尔型:boolean 引用类型: 类类型: 接口类型: 数组类型: Byte 1字节 八位 -128 -------- 127 short 2字节...

audience_1
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部