jQuery鼠标指针特效

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

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

posted @ 2024-07-18 10:40  僵小七  阅读(160)  评论(0编辑  收藏  举报