首页 > 其他分享 >Android 11 NavigationBar && Status Bar 如果改变背景颜色

Android 11 NavigationBar && Status Bar 如果改变背景颜色

时间:2024-07-18 10:40:08浏览次数:15  
标签:11 Status Bar Window window Activity java android view

SystemUI的导航栏和状态栏的背景是大部分是根据当前应用的主题显示的,状态有 黑,白,透明,半透明等.

需求:要求背景不跟随栈顶应用主题变化,始终固定成一个颜色!

/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java

    //NavigationBarView初始化
    public NavigationBarView(Context context, AttributeSet attrs) {
        super(context, attrs);
 
        ...
        mBarTransitions = new NavigationBarTransitions(this, Dependency.get(CommandQueue.class));
        ...
    }

/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java(导航栏背景过渡)

    //NavigationBarTransitions 继承了BarTransitions
    public NavigationBarTransitions(NavigationBarView view, CommandQueue commandQueue) {
        super(view, R.drawable.nav_background);//调用了父类的构造方法,并且传一个背景颜色
        mView = view;
        mLightTransitionsController = new LightBarTransitionsController(
                view.getContext(), this, commandQueue);
        ...        

    }
    
/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
    
    public BarTransitions(View view, int gradientResourceId) {
        mTag = "BarTransitions." + view.getClass().getSimpleName();
        mView = view;
        mBarBackground = new BarBackgroundDrawable(mView.getContext(), gradientResourceId);
        mView.setBackground(mBarBackground);//不管布局文件里面怎么改变背景颜色,最后的颜色都会在这里被重新设置!
    }
    
    //BarBackgroundDrawable 是BarTransitions的一个内部类,所以改变mBarBackground,就能改变背景颜色!
    //BarBackgroundDrawable里面有个onDraw的函数,可以通过改mMode的数值,改颜色
    
        @Override
        public void draw(Canvas canvas) {
            int targetGradientAlpha = 0, targetColor = 0;
            if (mMode == MODE_WARNING) {
                targetColor = mWarning;
            } else if (mMode == MODE_TRANSLUCENT) {
                targetColor = mSemiTransparent;
            } else if (mMode == MODE_SEMI_TRANSPARENT) {
                targetColor = mSemiTransparent;
            } else if (mMode == MODE_TRANSPARENT || mMode == MODE_LIGHTS_OUT_TRANSPARENT) {
                targetColor = mTransparent;
            } else {
                targetColor = mOpaque;
            }
        ...
   
/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java(状态栏背景过渡)
//跟上面的流程差不多



//Android 11 修改底部导航栏显示半透明背景/透明背景 部分应用没看到效果,Settings可以
/frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java

public class PhoneWindow extends Window implements MenuBuilder.Callback {
             mIsTranslucent = a.getBoolean(R.styleable.Window_windowIsTranslucent, false);

        final Context context = getContext();
        final int targetSdk = context.getApplicationInfo().targetSdkVersion;
        final boolean targetPreL = targetSdk < android.os.Build.VERSION_CODES.LOLLIPOP;
        final boolean targetPreQ = targetSdk < Build.VERSION_CODES.Q;

        //mForcedStatusBarColor 强制状态栏的颜色
        if (!mForcedStatusBarColor) {
            mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, 0xFF000000);
        }
        //mForcedNavigationBarColor 强制导航栏的颜色
        if (!mForcedNavigationBarColor) {
            mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
            mNavigationBarDividerColor = a.getColor(R.styleable.Window_navigationBarDividerColor,
                    0x00000000);
        }
        if (!targetPreQ) {
            mEnsureStatusBarContrastWhenTransparent = a.getBoolean(
                    R.styleable.Window_enforceStatusBarContrast, false);
-            mEnsureNavigationBarContrastWhenTransparent = a.getBoolean(
                    R.styleable.Window_enforceNavigationBarContrast, true);
+            mEnsureNavigationBarContrastWhenTransparent = a.getBoolean(
                    R.styleable.Window_enforceNavigationBarContrast, false);
        }
        ...

    
    //系统关于NavigationBarColor的函数
    @Override
    public int getNavigationBarColor() {
        return mNavigationBarColor;
    }

    @Override
    public void setNavigationBarColor(int color) {
        mNavigationBarColor = color;
        mForcedNavigationBarColor = true;
        if (mDecor != null) {
            mDecor.updateColorViews(null, false /* animate */);
        }
        final WindowControllerCallback callback = getWindowControllerCallback();
        if (callback != null) {
            getWindowControllerCallback().updateNavigationBarColor(color);
        }
    }
    
//app层窗口等级图
------Activity----------------------|
  ----PhoneWindow-------------------|
    --DecorView---------------------|
     -content-----------------------|
      ViewGroup->view(各种控件)      |
------------------------------------|     

DecorView:每个Activity对应一个DecorView。DecorView是真正的顶层View,是最外层的view。
其inflate(填充) PhoneWidow传过来的layout后,将其addView作为自己的第0个类。
DecorView维护了一个窗口的基本结构,包括主内容区域、titlebar区域等


//系统的某些apk 调用setNavigationBarColor()设置导航栏颜色
./packages/apps/DocumentsUI/src/com/android/documentsui/BaseActivity.java:438: 
getWindow().setNavigationBarColor(Color.TRANSPARENT);

./packages/apps/DocumentsUI/src/com/android/documentsui/BaseActivity.java:441: 
getWindow().setNavigationBarColor(getColor(R.color.nav_bar_translucent));


利用上面这一点,在framework层启动app的节点,都调用上述函数(setNavigationBarColor),是导航栏变为透明/半透明

当进入一个Activity后,会执行attach()→onCreate()
{
     setContentView(R.layout.activity_main);//设置布局,加载布局文件
}
→onStart()→onRestoreInstanceState()→onPostCreate()→onResume()
{
    //onResume执行完之后,用户可以看见界面(View)
}...

ActivityThread extends ClientTransactionHandler,ActivityThread的handler调用handleLaunchActivity处理启动Activity的消息

ActivityThread::performLaunchActivity和ActivityThread::handleResumeActivity,

performLaunchActivity会调用Activity的onCreate,onStart,onResotreInstanceState方法,
handleResumeActivity会调用Activity的onResume方法.

./frameworks/base/core/java/android/app/ActivityThread.java
    @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        // TODO Push resumeArgs into the activity for consideration
        //注:执行onResum
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
        if (r == null) {
            // We didn't actually resume the activity, so skipping any follow-up actions.
            return;
        }
        ...

        final Activity a = r.activity;

        if (localLOGV) {
            Slog.v(TAG, "Resume " + r + " started activity: " + a.mStartedActivity
                    + ", hideForNow: " + r.hideForNow + ", finished: " + a.mFinished);
        }

        final int forwardBit = isForward
                ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

        // If the window hasn't yet been added to the window manager,
        // and this guy didn't finish itself or start another activity,
        // then go ahead and add the window.
        boolean willBeVisible = !a.mStartedActivity;
        if (!willBeVisible) {
            try {
                willBeVisible = ActivityTaskManager.getService().willActivityBeVisible(
                        a.getActivityToken());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        //这里是处理Activity的View显示的
        if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            //add text
            //r.window.setNavigationBarColor(Color.TRANSPARENT);//透明/半透明
            r.window.setNavigationBarColor(Color.BLACK);
            //add text
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (r.mPreserveWindow) {
                a.mWindowAdded = true;
                r.mPreserveWindow = false;
                // Normally the ViewRoot sets up callbacks with the Activity
                // in addView->ViewRootImpl#setView. If we are instead reusing
                // the decor view we have to notify the view root that the
                // callbacks may have changed.
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl != null) {
                    impl.notifyChildRebuilt();
                }
            }
            ...

Window详解-wms

标签:11,Status,Bar,Window,window,Activity,java,android,view
From: https://www.cnblogs.com/kato-T/p/18308982

相关文章

  • Linux使用Ambari启动服务启动失败
    试了好几次,基本上所有服务都是启动失败,试过重启,网上也没有相关问题。这些全是红色,启动失败 打开日志后发现了很多问题:2024-07-1809:50:26,791-Retryingafter10seconds.Reason:Executionof'/usr/hdp/current/hadoop-hdfs-namenode/bin/hdfsdfsadmin-fshdfs://m......
  • 记录一次在欧拉(openEuler22.03LTS-SP4)系统下安装(踩坑)Freeswitch1.10.11的全过程
    目录前言安装环境1.下载Freeswitch1.1gitclone下载freeswitch库1.2官网下载2.开始安装前的工作2.1安装编译时需要的环境【先安装这个!】2.2configure前需要安装的库2.2.1.spandsp2.2.2.sofia-sip2.2.3.libks2.2.4.signalwire-c2.2.5x2642.2.6.libav2.2.6.1可能出现......
  • django“晋农进商”农产品跨境电子商务平台-计算机毕业设计源码60211
    摘要在全球化的浪潮下,电子商务已成为连接各国市场、促进贸易往来的重要桥梁。特别是在农产品领域,跨境电子商务平台的崛起不仅打破了地域限制,也为农民和消费者提供了前所未有的便利与机遇。在这一背景下,“晋农进商”农产品跨境电子商务平台应运而生,旨在将山西乃至全国的优质农......
  • test111_2
    web3题目更简单的web题分析代码出现include,猜测是文件包含漏洞。通过data://数据流+php命令执行函数查询当前工作目录下的内容,使用hackbar需要先进行url编码:得到flag文件名和首页文件:?url=data://text/plain,%3C%3Fphp%0Asystem('catctf_go_go_go')%3B%......
  • test111_1
    web签到题题目web签到题分析F12打开html文件:将注释进行Base64解码得到flag。web2题目最简单的SQL注入分析看着应该是SQL注入题。先尝试使用admin和123456登录,发现没有任何回显。看来报错被屏蔽了。显然admin栏如果注入成功则属于字符型注入。尝试......
  • 1143 多少个Fibonacci数
    首先,我们需要生成一个Fibonacci数列,直到其值超过10^100。由于Fibonacci数列的性质,我们知道这个数列的长度不会超过500。然后,对于每一对输入的a和b,我们在生成的Fibonacci数列中查找在a和b之间的数的个数。这可以通过二分查找来实现,因为Fibonacci数列是有序的。以下是对应的C+......
  • laravel11: 给接口增加签名验证
    一,添加controller/中间件/路由1,添加中间件liuhongdi@lhdpc:/data/site/gsapi$phpartisanmake:middlewareApiSignINFOMiddleware[app/Http/Middleware/ApiSign.php]createdsuccessfully.2,添加路由:在routes/api.php文件中Route::controller(VirtualControlle......
  • redis学习-11(缓存)
    缓存的收益和成本分析收益:1)加速读写2)降低后端负载成本:1)数据不一致性2)代码维护成本3)运维成本使用场景:1)开销大的复杂计算2)加速请求响应缓存更新策略的选择和使用场景LRU/LFU/FIFO算法剔除:当缓存使用量大于预设的最大值时候,对现有数据进行剔除,一致性最差,维护成本低超时剔......
  • 7月11号问答
    问题零:docker的⽹络模式有哪些,默认是⽹络模式是什么Docker网络模式配置说明host模式–net=host容器和宿主机共享Networknamespace。容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。网络性能比较好,但是dockerhost上已经使用的端口就不能再用了,网络的隔离......
  • iOS开发基础119-组件化
    一、引言组件化是将应用程序分解成多个独立模块的设计方法,这些模块可以单独开发、测试和维护。对于大型iOS项目,组件化能够提高开发效率、降低耦合、增加代码复用性,并且使项目更易维护。本文将详细介绍如何在iOS项目中实现组件化,包括本地组件管理和远程组件管理。二、为什么......