简介:当打开第三方App时,一般都是铺满整个屏幕,从而使得状态栏颜色发生变化,本文简单的分析下SystemUI方面StatusBar的Icon图标的颜色变化流程
本文从CommandQueue类开始分析,源码位于
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\CommandQueue.java
public void appTransitionStarting(long startTime, long duration) {
synchronized (mLock) {
mHandler.removeMessages(MSG_APP_TRANSITION_STARTING);
//发送一个MSG_APP_TRANSITION_STARTING消息
mHandler.obtainMessage(MSG_APP_TRANSITION_STARTING, Pair.create(startTime, duration)) .sendToTarget();
}
}
mHander是CommandQueue中的一个内部类,主要用于消息的接收:
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
switch (what) {
...........................................
case MSG_APP_TRANSITION_STARTING:
Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
mCallbacks.appTransitionStarting(data.first, data.second);
break;
......................
}
以上代码有部分省略,想深入研究的朋友可以查看源代码进行相应的分析。从上面可以看出对于消息的处理主要是回调mCallbacks的appTransitionSarting()函数;那么mCallbacks又是从哪传入呢?通过在SystemUI文件夹搜索,可以看出BaseStatusBar实现了CommandQueue.Callbacks,且在文件中有:
public void start() {
..............
// Connect in to the status bar manager service
//CommandQueue的构造函数传入参数就是CallBacks的具体实现者,而PhoneStatusBar是BaseStatusBar的具体实现者
mCommandQueue = new CommandQueue(this);
..............
}
由此转入到真正实现者PhoneStatusBar进行处理,其源码位于
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\PhoneStatusBar.java
@Override
public void appTransitionStarting(long startTime, long duration) {
// Use own timings when Keyguard is going away, see keyguardGoingAway and
// setKeyguardFadingAway.
//解锁之后:mKeyguardGoingAway=false,所以走mIconController分支
if (!mKeyguardGoingAway) {
mIconController.appTransitionStarting(startTime, duration);
}
if (mIconPolicy != null) {
mIconPolicy.appTransitionStarting(startTime, duration);
}
}
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\StatusBarIconController.java
public void appTransitionStarting(long startTime, long duration) {
if (mTransitionPending && mTintChangePending) {
mTintChangePending = false;
//状态栏图标颜色变化动画
animateIconTint(mPendingDarkIntensity,
Math.max(0, startTime - SystemClock.uptimeMillis()),
duration);
} else if (mTransitionPending) {
// If we don't have a pending tint change yet, the change might come in the future until
// startTime is reached.
mTransitionDeferring = true;
mTransitionDeferringStartTime = startTime;
mTransitionDeferringDuration = duration;
mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
}
mTransitionPending = false;
}
private void animateIconTint(float targetDarkIntensity, long delay,
long duration) {
if (mTintAnimator != null) {
mTintAnimator.cancel();
}
if (mDarkIntensity == targetDarkIntensity) {
return;
}
mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
mTintAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
/**
* 通过这样一个监听事件,我们就可以获取
* 到ValueAnimator每一步所产生的值。
*
* 通过调用getAnimatedValue()获取到每个时间因子所产生的Value。
* */
setIconTintInternal((Float) animation.getAnimatedValue());
}
});
mTintAnimator.setDuration(duration);
mTintAnimator.setStartDelay(delay);
mTintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
mTintAnimator.start();
}
private void setIconTintInternal(float darkIntensity) {
mDarkIntensity = darkIntensity;
//mIconTint 图标颜色适配获取变量,默认为白色,在此是获取适配的颜色
mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
mLightModeIconColorSingleTone, mDarkModeIconColorSingleTone);
mNotificationIconAreaController.setIconTint(mIconTint);
//应用适配的颜色
applyIconTint();
}
在该函数中有个mIconTint颜色适配,主要是通过获取ArgbEvaluator的实例,通过其evaluate()函数计算出其过渡每一时段的颜色;
mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone); //纯黑色
mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone); //纯白色
即上述函数的含义是:通过获取ValueAnimator每一个过渡时段的时间因子Value,在纯白色和纯黑色之间计算出一个合适的颜色值mIconTint,来适配对应的状态栏颜色。
applyIconTint即完成对应的StatusBar的状态栏图标的颜色适配:
private void applyIconTint() {
for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
StatusBarIconView v = (StatusBarIconView) mStatusIcons.getChildAt(i);
v.setImageTintList(ColorStateList.valueOf(getTint(mTintArea, v, mIconTint)));
}
mSignalCluster.setIconTint(mIconTint, mDarkIntensity, mTintArea);
mBatteryMeterView.setDarkIntensity(
isInArea(mTintArea, mBatteryMeterView) ? mDarkIntensity : 0);
mClock.setTextColor(getTint(mTintArea, mClock, mIconTint));
}