Merge changes Ibdf9cf90,I3a6dd476,Id4008fc7,Iede88d1e into oc-dev
* changes: NotificationViewWrapper: Fix crash for custom views Revert "Revert "AOD: Use color filter to invert icons for AOD"" Revert "Revert "NotificationWrappers: Factor out doze treatment"" AOD: prevent clicking shelf when dark
This commit is contained in:
committed by
Android (Google) Code Review
commit
debabde073
@@ -23,7 +23,6 @@ import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.internal.widget.CachingIconView;
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.ViewInvertHelper;
|
||||
@@ -127,12 +126,8 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
||||
super.setDark(dark, fade, delay);
|
||||
if (mDark == dark) return;
|
||||
mDark = dark;
|
||||
if (fade) {
|
||||
mViewInvertHelper.fade(dark, delay);
|
||||
} else {
|
||||
mViewInvertHelper.update(dark);
|
||||
}
|
||||
mShelfIcons.setAmbient(dark);
|
||||
mShelfIcons.setDark(dark, fade, delay);
|
||||
updateInteractiveness();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -576,7 +571,8 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
||||
}
|
||||
|
||||
private void updateInteractiveness() {
|
||||
mInteractive = mStatusBarState == StatusBarState.KEYGUARD && mHasItemsInStableShelf;
|
||||
mInteractive = mStatusBarState == StatusBarState.KEYGUARD && mHasItemsInStableShelf
|
||||
&& !mDark;
|
||||
setClickable(mInteractive);
|
||||
setFocusable(mInteractive);
|
||||
setImportantForAccessibility(mInteractive ? View.IMPORTANT_FOR_ACCESSIBILITY_YES
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -46,6 +47,7 @@ import android.view.animation.Interpolator;
|
||||
import com.android.internal.statusbar.StatusBarIcon;
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.notification.NotificationIconDozeHelper;
|
||||
import com.android.systemui.statusbar.notification.NotificationUtils;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
@@ -99,7 +101,6 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
private int mDensity;
|
||||
private float mIconScale = 1.0f;
|
||||
private final Paint mDotPaint = new Paint();
|
||||
private boolean mDotVisible;
|
||||
private float mDotRadius;
|
||||
private int mStaticDotRadius;
|
||||
private int mVisibleState = STATE_ICON;
|
||||
@@ -110,6 +111,8 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
private OnVisibilityChangedListener mOnVisibilityChangedListener;
|
||||
private int mDrawableColor;
|
||||
private int mIconColor;
|
||||
private int mDecorColor;
|
||||
private float mDarkAmount;
|
||||
private ValueAnimator mColorAnimator;
|
||||
private int mCurrentSetColor = NO_COLOR;
|
||||
private int mAnimationStartColor = NO_COLOR;
|
||||
@@ -119,6 +122,7 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
animation.getAnimatedFraction());
|
||||
setColorInternal(newColor);
|
||||
};
|
||||
private final NotificationIconDozeHelper mDozer;
|
||||
|
||||
public StatusBarIconView(Context context, String slot, Notification notification) {
|
||||
this(context, slot, notification, false);
|
||||
@@ -127,6 +131,7 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
public StatusBarIconView(Context context, String slot, Notification notification,
|
||||
boolean blocked) {
|
||||
super(context);
|
||||
mDozer = new NotificationIconDozeHelper(context);
|
||||
mBlocked = blocked;
|
||||
mSlot = slot;
|
||||
mNumberPain = new Paint();
|
||||
@@ -190,6 +195,7 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
|
||||
public StatusBarIconView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mDozer = new NotificationIconDozeHelper(context);
|
||||
mBlocked = false;
|
||||
mAlwaysScaleIcon = true;
|
||||
updateIconScale();
|
||||
@@ -466,7 +472,19 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
* to the drawable.
|
||||
*/
|
||||
public void setDecorColor(int iconTint) {
|
||||
mDotPaint.setColor(iconTint);
|
||||
mDecorColor = iconTint;
|
||||
updateDecorColor();
|
||||
}
|
||||
|
||||
private void updateDecorColor() {
|
||||
int color = NotificationUtils.interpolateColors(mDecorColor, Color.WHITE, mDarkAmount);
|
||||
if (mDotPaint.getColor() != color) {
|
||||
mDotPaint.setColor(color);
|
||||
|
||||
if (mDotAppearAmount != 0) {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -477,6 +495,7 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
mDrawableColor = color;
|
||||
setColorInternal(color);
|
||||
mIconColor = color;
|
||||
mDozer.setColor(color);
|
||||
}
|
||||
|
||||
private void setColorInternal(int color) {
|
||||
@@ -649,6 +668,14 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
mOnVisibilityChangedListener = listener;
|
||||
}
|
||||
|
||||
public void setDark(boolean dark, boolean fade, long delay) {
|
||||
mDozer.setImageDark(this, dark, fade, delay, mIconColor == NO_COLOR);
|
||||
mDozer.setIntensityDark(f -> {
|
||||
mDarkAmount = f;
|
||||
updateDecorColor();
|
||||
}, dark, fade, delay);
|
||||
}
|
||||
|
||||
public interface OnVisibilityChangedListener {
|
||||
void onVisibilityChanged(int newVisibility);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.view.View;
|
||||
@@ -38,8 +38,8 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper {
|
||||
private boolean mIsLegacy;
|
||||
private int mLegacyColor;
|
||||
|
||||
protected NotificationCustomViewWrapper(View view, ExpandableNotificationRow row) {
|
||||
super(view, row);
|
||||
protected NotificationCustomViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
|
||||
super(ctx, view, row);
|
||||
mInvertHelper = new ViewInvertHelper(view, NotificationPanelView.DOZE_ANIMATION_DURATION);
|
||||
mLegacyColor = row.getContext().getColor(R.color.notification_legacy_background_color);
|
||||
}
|
||||
@@ -67,13 +67,11 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper {
|
||||
}
|
||||
|
||||
protected void fadeGrayscale(final boolean dark, long delay) {
|
||||
startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
updateGrayscaleMatrix((float) animation.getAnimatedValue());
|
||||
mGreyPaint.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
|
||||
mView.setLayerPaint(mGreyPaint);
|
||||
}
|
||||
getDozer().startIntensityAnimation(animation -> {
|
||||
getDozer().updateGrayscaleMatrix((float) animation.getAnimatedValue());
|
||||
mGreyPaint.setColorFilter(
|
||||
new ColorMatrixColorFilter(getDozer().getGrayscaleColorMatrix()));
|
||||
mView.setLayerPaint(mGreyPaint);
|
||||
}, dark, delay, new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
@@ -86,9 +84,9 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper {
|
||||
|
||||
protected void updateGrayscale(boolean dark) {
|
||||
if (dark) {
|
||||
updateGrayscaleMatrix(1f);
|
||||
getDozer().updateGrayscaleMatrix(1f);
|
||||
mGreyPaint.setColorFilter(
|
||||
new ColorMatrixColorFilter(mGrayscaleColorMatrix));
|
||||
new ColorMatrixColorFilter(getDozer().getGrayscaleColorMatrix()));
|
||||
mView.setLayerPaint(mGreyPaint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.notification;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.statusbar.phone.NotificationPanelView;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class NotificationDozeHelper {
|
||||
private final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
|
||||
|
||||
public void fadeGrayscale(final ImageView target, final boolean dark, long delay) {
|
||||
startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
updateGrayscaleMatrix((float) animation.getAnimatedValue());
|
||||
target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
|
||||
}
|
||||
}, dark, delay, new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (!dark) {
|
||||
target.setColorFilter(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void updateGrayscale(ImageView target, boolean dark) {
|
||||
if (dark) {
|
||||
updateGrayscaleMatrix(1f);
|
||||
target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
|
||||
} else {
|
||||
target.setColorFilter(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
|
||||
boolean dark, long delay, Animator.AnimatorListener listener) {
|
||||
float startIntensity = dark ? 0f : 1f;
|
||||
float endIntensity = dark ? 1f : 0f;
|
||||
ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
|
||||
animator.addUpdateListener(updateListener);
|
||||
animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
|
||||
animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
|
||||
animator.setStartDelay(delay);
|
||||
if (listener != null) {
|
||||
animator.addListener(listener);
|
||||
}
|
||||
animator.start();
|
||||
}
|
||||
|
||||
public void setIntensityDark(Consumer<Float> listener, boolean dark,
|
||||
boolean animate, long delay) {
|
||||
if (animate) {
|
||||
startIntensityAnimation(a -> listener.accept((Float) a.getAnimatedValue()), dark, delay,
|
||||
null /* listener */);
|
||||
} else {
|
||||
listener.accept(dark ? 1f : 0f);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateGrayscaleMatrix(float intensity) {
|
||||
mGrayscaleColorMatrix.setSaturation(1 - intensity);
|
||||
}
|
||||
|
||||
public ColorMatrix getGrayscaleColorMatrix() {
|
||||
return mGrayscaleColorMatrix;
|
||||
}
|
||||
}
|
||||
@@ -16,17 +16,10 @@
|
||||
|
||||
package com.android.systemui.statusbar.notification;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.ArraySet;
|
||||
import android.view.NotificationHeaderView;
|
||||
import android.view.View;
|
||||
@@ -37,7 +30,6 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.ViewInvertHelper;
|
||||
import com.android.systemui.statusbar.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.TransformableView;
|
||||
@@ -55,10 +47,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
|
||||
private static final Interpolator LOW_PRIORITY_HEADER_CLOSE
|
||||
= new PathInterpolator(0.4f, 0f, 0.7f, 1f);
|
||||
private final PorterDuffColorFilter mIconColorFilter = new PorterDuffColorFilter(
|
||||
0, PorterDuff.Mode.SRC_ATOP);
|
||||
private final int mIconDarkAlpha;
|
||||
private final int mIconDarkColor = 0xffffffff;
|
||||
|
||||
protected final ViewInvertHelper mInvertHelper;
|
||||
protected final ViewTransformationHelper mTransformationHelper;
|
||||
@@ -74,8 +62,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
private boolean mTransformLowPriorityTitle;
|
||||
|
||||
protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
|
||||
super(view, row);
|
||||
mIconDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
|
||||
super(ctx, view, row);
|
||||
mInvertHelper = new ViewInvertHelper(ctx, NotificationPanelView.DOZE_ANIMATION_DURATION);
|
||||
mTransformationHelper = new ViewTransformationHelper();
|
||||
|
||||
@@ -108,6 +95,16 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
updateInvertHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NotificationDozeHelper createDozer(Context ctx) {
|
||||
return new NotificationIconDozeHelper(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NotificationIconDozeHelper getDozer() {
|
||||
return (NotificationIconDozeHelper) super.getDozer();
|
||||
}
|
||||
|
||||
protected void resolveHeaderViews() {
|
||||
mIcon = (ImageView) mView.findViewById(com.android.internal.R.id.icon);
|
||||
mHeaderText = (TextView) mView.findViewById(com.android.internal.R.id.header_text);
|
||||
@@ -116,6 +113,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
mColor = resolveColor(mExpandButton);
|
||||
mNotificationHeader = (NotificationHeaderView) mView.findViewById(
|
||||
com.android.internal.R.id.notification_header);
|
||||
getDozer().setColor(mColor);
|
||||
}
|
||||
|
||||
private int resolveColor(ImageView icon) {
|
||||
@@ -223,90 +221,8 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
// It also may lead to bugs where the icon isn't correctly greyed out.
|
||||
boolean hadColorFilter = mNotificationHeader.getOriginalIconColor()
|
||||
!= NotificationHeaderView.NO_COLOR;
|
||||
if (fade) {
|
||||
if (hadColorFilter) {
|
||||
fadeIconColorFilter(mIcon, dark, delay);
|
||||
fadeIconAlpha(mIcon, dark, delay);
|
||||
} else {
|
||||
fadeGrayscale(mIcon, dark, delay);
|
||||
}
|
||||
} else {
|
||||
if (hadColorFilter) {
|
||||
updateIconColorFilter(mIcon, dark);
|
||||
updateIconAlpha(mIcon, dark);
|
||||
} else {
|
||||
updateGrayscale(mIcon, dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fadeIconColorFilter(final ImageView target, boolean dark, long delay) {
|
||||
startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
updateIconColorFilter(target, (Float) animation.getAnimatedValue());
|
||||
}
|
||||
}, dark, delay, null /* listener */);
|
||||
}
|
||||
|
||||
private void fadeIconAlpha(final ImageView target, boolean dark, long delay) {
|
||||
startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
float t = (float) animation.getAnimatedValue();
|
||||
target.setImageAlpha((int) (255 * (1f - t) + mIconDarkAlpha * t));
|
||||
}
|
||||
}, dark, delay, null /* listener */);
|
||||
}
|
||||
|
||||
protected void fadeGrayscale(final ImageView target, final boolean dark, long delay) {
|
||||
startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
updateGrayscaleMatrix((float) animation.getAnimatedValue());
|
||||
target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
|
||||
}
|
||||
}, dark, delay, new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (!dark) {
|
||||
target.setColorFilter(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateIconColorFilter(ImageView target, boolean dark) {
|
||||
updateIconColorFilter(target, dark ? 1f : 0f);
|
||||
}
|
||||
|
||||
private void updateIconColorFilter(ImageView target, float intensity) {
|
||||
int color = interpolateColor(mColor, mIconDarkColor, intensity);
|
||||
mIconColorFilter.setColor(color);
|
||||
Drawable iconDrawable = target.getDrawable();
|
||||
|
||||
// Also, the notification might have been modified during the animation, so background
|
||||
// might be null here.
|
||||
if (iconDrawable != null) {
|
||||
Drawable d = iconDrawable.mutate();
|
||||
// DrawableContainer ignores the color filter if it's already set, so clear it first to
|
||||
// get it set and invalidated properly.
|
||||
d.setColorFilter(null);
|
||||
d.setColorFilter(mIconColorFilter);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateIconAlpha(ImageView target, boolean dark) {
|
||||
target.setImageAlpha(dark ? mIconDarkAlpha : 255);
|
||||
}
|
||||
|
||||
protected void updateGrayscale(ImageView target, boolean dark) {
|
||||
if (dark) {
|
||||
updateGrayscaleMatrix(1f);
|
||||
target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
|
||||
} else {
|
||||
target.setColorFilter(null);
|
||||
getDozer().setImageDark(mIcon, dark, fade, delay, !hadColorFilter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,22 +232,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
mNotificationHeader.setOnClickListener(expandable ? onClickListener : null);
|
||||
}
|
||||
|
||||
private static int interpolateColor(int source, int target, float t) {
|
||||
int aSource = Color.alpha(source);
|
||||
int rSource = Color.red(source);
|
||||
int gSource = Color.green(source);
|
||||
int bSource = Color.blue(source);
|
||||
int aTarget = Color.alpha(target);
|
||||
int rTarget = Color.red(target);
|
||||
int gTarget = Color.green(target);
|
||||
int bTarget = Color.blue(target);
|
||||
return Color.argb(
|
||||
(int) (aSource * (1f - t) + aTarget * t),
|
||||
(int) (rSource * (1f - t) + rTarget * t),
|
||||
(int) (gSource * (1f - t) + gTarget * t),
|
||||
(int) (bSource * (1f - t) + bTarget * t));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NotificationHeaderView getNotificationHeader() {
|
||||
return mNotificationHeader;
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.notification;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
public class NotificationIconDozeHelper extends NotificationDozeHelper {
|
||||
|
||||
private final int mImageDarkAlpha;
|
||||
private final int mImageDarkColor = 0xffffffff;
|
||||
private final PorterDuffColorFilter mImageColorFilter = new PorterDuffColorFilter(
|
||||
0, PorterDuff.Mode.SRC_ATOP);
|
||||
|
||||
private int mColor = Color.BLACK;
|
||||
|
||||
public NotificationIconDozeHelper(Context ctx) {
|
||||
mImageDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
public void setImageDark(ImageView target, boolean dark, boolean fade, long delay,
|
||||
boolean useGrayscale) {
|
||||
if (fade) {
|
||||
if (!useGrayscale) {
|
||||
fadeImageColorFilter(target, dark, delay);
|
||||
fadeImageAlpha(target, dark, delay);
|
||||
} else {
|
||||
fadeGrayscale(target, dark, delay);
|
||||
}
|
||||
} else {
|
||||
if (!useGrayscale) {
|
||||
updateImageColorFilter(target, dark);
|
||||
updateImageAlpha(target, dark);
|
||||
} else {
|
||||
updateGrayscale(target, dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fadeImageColorFilter(final ImageView target, boolean dark, long delay) {
|
||||
startIntensityAnimation(animation -> {
|
||||
updateImageColorFilter(target, (Float) animation.getAnimatedValue());
|
||||
}, dark, delay, null /* listener */);
|
||||
}
|
||||
|
||||
private void fadeImageAlpha(final ImageView target, boolean dark, long delay) {
|
||||
startIntensityAnimation(animation -> {
|
||||
float t = (float) animation.getAnimatedValue();
|
||||
target.setImageAlpha((int) (255 * (1f - t) + mImageDarkAlpha * t));
|
||||
}, dark, delay, null /* listener */);
|
||||
}
|
||||
|
||||
private void updateImageColorFilter(ImageView target, boolean dark) {
|
||||
updateImageColorFilter(target, dark ? 1f : 0f);
|
||||
}
|
||||
|
||||
private void updateImageColorFilter(ImageView target, float intensity) {
|
||||
int color = NotificationUtils.interpolateColors(mColor, mImageDarkColor, intensity);
|
||||
mImageColorFilter.setColor(color);
|
||||
Drawable imageDrawable = target.getDrawable();
|
||||
|
||||
// Also, the notification might have been modified during the animation, so background
|
||||
// might be null here.
|
||||
if (imageDrawable != null) {
|
||||
Drawable d = imageDrawable.mutate();
|
||||
// DrawableContainer ignores the color filter if it's already set, so clear it first to
|
||||
// get it set and invalidated properly.
|
||||
d.setColorFilter(null);
|
||||
d.setColorFilter(mImageColorFilter);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateImageAlpha(ImageView target, boolean dark) {
|
||||
target.setImageAlpha(dark ? mImageDarkAlpha : 255);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.systemui.statusbar.notification;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
@@ -46,7 +45,8 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
|
||||
private int mContentHeight;
|
||||
private int mMinHeightHint;
|
||||
|
||||
protected NotificationTemplateViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
|
||||
protected NotificationTemplateViewWrapper(Context ctx, View view,
|
||||
ExpandableNotificationRow row) {
|
||||
super(ctx, view, row);
|
||||
mTransformationHelper.setCustomTransformation(
|
||||
new ViewTransformationHelper.CustomTransformation() {
|
||||
@@ -154,16 +154,20 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
|
||||
// This also clears the existing types
|
||||
super.updateTransformedTypes();
|
||||
if (mTitle != null) {
|
||||
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE, mTitle);
|
||||
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
|
||||
mTitle);
|
||||
}
|
||||
if (mText != null) {
|
||||
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT, mText);
|
||||
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
|
||||
mText);
|
||||
}
|
||||
if (mPicture != null) {
|
||||
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE, mPicture);
|
||||
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE,
|
||||
mPicture);
|
||||
}
|
||||
if (mProgressBar != null) {
|
||||
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS, mProgressBar);
|
||||
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS,
|
||||
mProgressBar);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +177,7 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
|
||||
return;
|
||||
}
|
||||
super.setDark(dark, fade, delay);
|
||||
setPictureGrayscale(dark, fade, delay);
|
||||
setPictureDark(dark, fade, delay);
|
||||
setProgressBarDark(dark, fade, delay);
|
||||
}
|
||||
|
||||
@@ -188,12 +192,9 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
|
||||
}
|
||||
|
||||
private void fadeProgressDark(final ProgressBar target, final boolean dark, long delay) {
|
||||
startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
float t = (float) animation.getAnimatedValue();
|
||||
updateProgressDark(target, t);
|
||||
}
|
||||
getDozer().startIntensityAnimation(animation -> {
|
||||
float t = (float) animation.getAnimatedValue();
|
||||
updateProgressDark(target, t);
|
||||
}, dark, delay, null /* listener */);
|
||||
}
|
||||
|
||||
@@ -207,13 +208,9 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
|
||||
updateProgressDark(target, dark ? 1f : 0f);
|
||||
}
|
||||
|
||||
protected void setPictureGrayscale(boolean grayscale, boolean fade, long delay) {
|
||||
private void setPictureDark(boolean dark, boolean fade, long delay) {
|
||||
if (mPicture != null) {
|
||||
if (fade) {
|
||||
fadeGrayscale(mPicture, grayscale, delay);
|
||||
} else {
|
||||
updateGrayscale(mPicture, grayscale);
|
||||
}
|
||||
getDozer().setImageDark(mPicture, dark, fade, delay, true /* useGrayscale */);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,24 +16,17 @@
|
||||
|
||||
package com.android.systemui.statusbar.notification;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.support.v4.graphics.ColorUtils;
|
||||
import android.view.NotificationHeaderView;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.CrossFadeHelper;
|
||||
import com.android.systemui.statusbar.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.TransformableView;
|
||||
import com.android.systemui.statusbar.phone.NotificationPanelView;
|
||||
|
||||
/**
|
||||
* Wraps the actual notification content view; used to implement behaviors which are different for
|
||||
@@ -41,14 +34,14 @@ import com.android.systemui.statusbar.phone.NotificationPanelView;
|
||||
*/
|
||||
public abstract class NotificationViewWrapper implements TransformableView {
|
||||
|
||||
protected final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
|
||||
protected final View mView;
|
||||
protected final ExpandableNotificationRow mRow;
|
||||
private final NotificationDozeHelper mDozer;
|
||||
|
||||
protected boolean mDark;
|
||||
private int mBackgroundColor = 0;
|
||||
protected boolean mShouldInvertDark;
|
||||
protected boolean mDarkInitialized = false;
|
||||
private boolean mForcedInvisible;
|
||||
|
||||
public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
|
||||
if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
|
||||
@@ -65,13 +58,22 @@ public abstract class NotificationViewWrapper implements TransformableView {
|
||||
} else if (v instanceof NotificationHeaderView) {
|
||||
return new NotificationHeaderViewWrapper(ctx, v, row);
|
||||
} else {
|
||||
return new NotificationCustomViewWrapper(v, row);
|
||||
return new NotificationCustomViewWrapper(ctx, v, row);
|
||||
}
|
||||
}
|
||||
|
||||
protected NotificationViewWrapper(View view, ExpandableNotificationRow row) {
|
||||
protected NotificationViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
|
||||
mView = view;
|
||||
mRow = row;
|
||||
mDozer = createDozer(ctx);
|
||||
}
|
||||
|
||||
protected NotificationDozeHelper createDozer(Context ctx) {
|
||||
return new NotificationDozeHelper();
|
||||
}
|
||||
|
||||
protected NotificationDozeHelper getDozer() {
|
||||
return mDozer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,26 +114,6 @@ public abstract class NotificationViewWrapper implements TransformableView {
|
||||
|| ColorUtils.calculateLuminance(backgroundColor) > 0.5;
|
||||
}
|
||||
|
||||
|
||||
protected void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
|
||||
boolean dark, long delay, Animator.AnimatorListener listener) {
|
||||
float startIntensity = dark ? 0f : 1f;
|
||||
float endIntensity = dark ? 1f : 0f;
|
||||
ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
|
||||
animator.addUpdateListener(updateListener);
|
||||
animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
|
||||
animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
|
||||
animator.setStartDelay(delay);
|
||||
if (listener != null) {
|
||||
animator.addListener(listener);
|
||||
}
|
||||
animator.start();
|
||||
}
|
||||
|
||||
protected void updateGrayscaleMatrix(float intensity) {
|
||||
mGrayscaleColorMatrix.setSaturation(1 - intensity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the appearance of the expand button.
|
||||
*
|
||||
|
||||
@@ -95,7 +95,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
private int mActualLayoutWidth = NO_VALUE;
|
||||
private float mActualPaddingEnd = NO_VALUE;
|
||||
private float mActualPaddingStart = NO_VALUE;
|
||||
private boolean mCentered;
|
||||
private boolean mDark;
|
||||
private boolean mChangingViewPositions;
|
||||
private int mAddAnimationStartIndex = -1;
|
||||
private int mCannedAnimationStartIndex = -1;
|
||||
@@ -183,6 +183,9 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, childIndex);
|
||||
}
|
||||
}
|
||||
if (mDark && child instanceof StatusBarIconView) {
|
||||
((StatusBarIconView) child).setDark(mDark, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -312,7 +315,8 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
numDots++;
|
||||
}
|
||||
}
|
||||
if (mCentered && translationX < getLayoutEnd()) {
|
||||
boolean center = mDark;
|
||||
if (center && translationX < getLayoutEnd()) {
|
||||
float delta = (getLayoutEnd() - translationX) / 2;
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View view = getChildAt(i);
|
||||
@@ -390,9 +394,15 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
mChangingViewPositions = changingViewPositions;
|
||||
}
|
||||
|
||||
public void setAmbient(boolean ambient) {
|
||||
mCentered = ambient;
|
||||
public void setDark(boolean dark, boolean fade, long delay) {
|
||||
mDark = dark;
|
||||
mDisallowNextAnimation = true;
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View view = getChildAt(i);
|
||||
if (view instanceof StatusBarIconView) {
|
||||
((StatusBarIconView) view).setDark(dark, fade, delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IconState getIconState(StatusBarIconView icon) {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.notification;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.systemui.statusbar.ExpandableNotificationRow;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class NotificationViewWrapperTest {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mContext = InstrumentationRegistry.getTargetContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructor_doesntUseViewContext() throws Exception {
|
||||
new TestableNotificationViewWrapper(mContext, new View(null /* context */), null /* row */);
|
||||
}
|
||||
|
||||
static class TestableNotificationViewWrapper extends NotificationViewWrapper {
|
||||
protected TestableNotificationViewWrapper(Context ctx, View view,
|
||||
ExpandableNotificationRow row) {
|
||||
super(ctx, view, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user