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:
TreeHugger Robot
2017-04-05 20:30:15 +00:00
committed by Android (Google) Code Review
10 changed files with 343 additions and 189 deletions

View File

@@ -23,7 +23,6 @@ import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.android.internal.widget.CachingIconView;
import com.android.systemui.Interpolators; import com.android.systemui.Interpolators;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.ViewInvertHelper; import com.android.systemui.ViewInvertHelper;
@@ -127,12 +126,8 @@ public class NotificationShelf extends ActivatableNotificationView implements
super.setDark(dark, fade, delay); super.setDark(dark, fade, delay);
if (mDark == dark) return; if (mDark == dark) return;
mDark = dark; mDark = dark;
if (fade) { mShelfIcons.setDark(dark, fade, delay);
mViewInvertHelper.fade(dark, delay); updateInteractiveness();
} else {
mViewInvertHelper.update(dark);
}
mShelfIcons.setAmbient(dark);
} }
@Override @Override
@@ -576,7 +571,8 @@ public class NotificationShelf extends ActivatableNotificationView implements
} }
private void updateInteractiveness() { private void updateInteractiveness() {
mInteractive = mStatusBarState == StatusBarState.KEYGUARD && mHasItemsInStableShelf; mInteractive = mStatusBarState == StatusBarState.KEYGUARD && mHasItemsInStableShelf
&& !mDark;
setClickable(mInteractive); setClickable(mInteractive);
setFocusable(mInteractive); setFocusable(mInteractive);
setImportantForAccessibility(mInteractive ? View.IMPORTANT_FOR_ACCESSIBILITY_YES setImportantForAccessibility(mInteractive ? View.IMPORTANT_FOR_ACCESSIBILITY_YES

View File

@@ -27,6 +27,7 @@ import android.content.res.ColorStateList;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@@ -46,6 +47,7 @@ import android.view.animation.Interpolator;
import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Interpolators; import com.android.systemui.Interpolators;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationIconDozeHelper;
import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.NotificationUtils;
import java.text.NumberFormat; import java.text.NumberFormat;
@@ -99,7 +101,6 @@ public class StatusBarIconView extends AnimatedImageView {
private int mDensity; private int mDensity;
private float mIconScale = 1.0f; private float mIconScale = 1.0f;
private final Paint mDotPaint = new Paint(); private final Paint mDotPaint = new Paint();
private boolean mDotVisible;
private float mDotRadius; private float mDotRadius;
private int mStaticDotRadius; private int mStaticDotRadius;
private int mVisibleState = STATE_ICON; private int mVisibleState = STATE_ICON;
@@ -110,6 +111,8 @@ public class StatusBarIconView extends AnimatedImageView {
private OnVisibilityChangedListener mOnVisibilityChangedListener; private OnVisibilityChangedListener mOnVisibilityChangedListener;
private int mDrawableColor; private int mDrawableColor;
private int mIconColor; private int mIconColor;
private int mDecorColor;
private float mDarkAmount;
private ValueAnimator mColorAnimator; private ValueAnimator mColorAnimator;
private int mCurrentSetColor = NO_COLOR; private int mCurrentSetColor = NO_COLOR;
private int mAnimationStartColor = NO_COLOR; private int mAnimationStartColor = NO_COLOR;
@@ -119,6 +122,7 @@ public class StatusBarIconView extends AnimatedImageView {
animation.getAnimatedFraction()); animation.getAnimatedFraction());
setColorInternal(newColor); setColorInternal(newColor);
}; };
private final NotificationIconDozeHelper mDozer;
public StatusBarIconView(Context context, String slot, Notification notification) { public StatusBarIconView(Context context, String slot, Notification notification) {
this(context, slot, notification, false); this(context, slot, notification, false);
@@ -127,6 +131,7 @@ public class StatusBarIconView extends AnimatedImageView {
public StatusBarIconView(Context context, String slot, Notification notification, public StatusBarIconView(Context context, String slot, Notification notification,
boolean blocked) { boolean blocked) {
super(context); super(context);
mDozer = new NotificationIconDozeHelper(context);
mBlocked = blocked; mBlocked = blocked;
mSlot = slot; mSlot = slot;
mNumberPain = new Paint(); mNumberPain = new Paint();
@@ -190,6 +195,7 @@ public class StatusBarIconView extends AnimatedImageView {
public StatusBarIconView(Context context, AttributeSet attrs) { public StatusBarIconView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
mDozer = new NotificationIconDozeHelper(context);
mBlocked = false; mBlocked = false;
mAlwaysScaleIcon = true; mAlwaysScaleIcon = true;
updateIconScale(); updateIconScale();
@@ -466,7 +472,19 @@ public class StatusBarIconView extends AnimatedImageView {
* to the drawable. * to the drawable.
*/ */
public void setDecorColor(int iconTint) { 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; mDrawableColor = color;
setColorInternal(color); setColorInternal(color);
mIconColor = color; mIconColor = color;
mDozer.setColor(color);
} }
private void setColorInternal(int color) { private void setColorInternal(int color) {
@@ -649,6 +668,14 @@ public class StatusBarIconView extends AnimatedImageView {
mOnVisibilityChangedListener = listener; 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 { public interface OnVisibilityChangedListener {
void onVisibilityChanged(int newVisibility); void onVisibilityChanged(int newVisibility);
} }

View File

@@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator; import android.content.Context;
import android.graphics.ColorMatrixColorFilter; import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint; import android.graphics.Paint;
import android.view.View; import android.view.View;
@@ -38,8 +38,8 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper {
private boolean mIsLegacy; private boolean mIsLegacy;
private int mLegacyColor; private int mLegacyColor;
protected NotificationCustomViewWrapper(View view, ExpandableNotificationRow row) { protected NotificationCustomViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
super(view, row); super(ctx, view, row);
mInvertHelper = new ViewInvertHelper(view, NotificationPanelView.DOZE_ANIMATION_DURATION); mInvertHelper = new ViewInvertHelper(view, NotificationPanelView.DOZE_ANIMATION_DURATION);
mLegacyColor = row.getContext().getColor(R.color.notification_legacy_background_color); 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) { protected void fadeGrayscale(final boolean dark, long delay) {
startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() { getDozer().startIntensityAnimation(animation -> {
@Override getDozer().updateGrayscaleMatrix((float) animation.getAnimatedValue());
public void onAnimationUpdate(ValueAnimator animation) { mGreyPaint.setColorFilter(
updateGrayscaleMatrix((float) animation.getAnimatedValue()); new ColorMatrixColorFilter(getDozer().getGrayscaleColorMatrix()));
mGreyPaint.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix)); mView.setLayerPaint(mGreyPaint);
mView.setLayerPaint(mGreyPaint);
}
}, dark, delay, new AnimatorListenerAdapter() { }, dark, delay, new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
@@ -86,9 +84,9 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper {
protected void updateGrayscale(boolean dark) { protected void updateGrayscale(boolean dark) {
if (dark) { if (dark) {
updateGrayscaleMatrix(1f); getDozer().updateGrayscaleMatrix(1f);
mGreyPaint.setColorFilter( mGreyPaint.setColorFilter(
new ColorMatrixColorFilter(mGrayscaleColorMatrix)); new ColorMatrixColorFilter(getDozer().getGrayscaleColorMatrix()));
mView.setLayerPaint(mGreyPaint); mView.setLayerPaint(mGreyPaint);
} }
} }

View File

@@ -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;
}
}

View File

@@ -16,17 +16,10 @@
package com.android.systemui.statusbar.notification; package com.android.systemui.statusbar.notification;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.Notification; import android.app.Notification;
import android.content.Context; import android.content.Context;
import android.graphics.Color;
import android.graphics.ColorFilter; import android.graphics.ColorFilter;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.util.ArraySet; import android.util.ArraySet;
import android.view.NotificationHeaderView; import android.view.NotificationHeaderView;
import android.view.View; import android.view.View;
@@ -37,7 +30,6 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.android.systemui.Interpolators; import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.ViewInvertHelper; import com.android.systemui.ViewInvertHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.TransformableView; import com.android.systemui.statusbar.TransformableView;
@@ -55,10 +47,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
private static final Interpolator LOW_PRIORITY_HEADER_CLOSE private static final Interpolator LOW_PRIORITY_HEADER_CLOSE
= new PathInterpolator(0.4f, 0f, 0.7f, 1f); = 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 ViewInvertHelper mInvertHelper;
protected final ViewTransformationHelper mTransformationHelper; protected final ViewTransformationHelper mTransformationHelper;
@@ -74,8 +62,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
private boolean mTransformLowPriorityTitle; private boolean mTransformLowPriorityTitle;
protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) { protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
super(view, row); super(ctx, view, row);
mIconDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
mInvertHelper = new ViewInvertHelper(ctx, NotificationPanelView.DOZE_ANIMATION_DURATION); mInvertHelper = new ViewInvertHelper(ctx, NotificationPanelView.DOZE_ANIMATION_DURATION);
mTransformationHelper = new ViewTransformationHelper(); mTransformationHelper = new ViewTransformationHelper();
@@ -108,6 +95,16 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
updateInvertHelper(); updateInvertHelper();
} }
@Override
protected NotificationDozeHelper createDozer(Context ctx) {
return new NotificationIconDozeHelper(ctx);
}
@Override
protected NotificationIconDozeHelper getDozer() {
return (NotificationIconDozeHelper) super.getDozer();
}
protected void resolveHeaderViews() { protected void resolveHeaderViews() {
mIcon = (ImageView) mView.findViewById(com.android.internal.R.id.icon); mIcon = (ImageView) mView.findViewById(com.android.internal.R.id.icon);
mHeaderText = (TextView) mView.findViewById(com.android.internal.R.id.header_text); mHeaderText = (TextView) mView.findViewById(com.android.internal.R.id.header_text);
@@ -116,6 +113,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
mColor = resolveColor(mExpandButton); mColor = resolveColor(mExpandButton);
mNotificationHeader = (NotificationHeaderView) mView.findViewById( mNotificationHeader = (NotificationHeaderView) mView.findViewById(
com.android.internal.R.id.notification_header); com.android.internal.R.id.notification_header);
getDozer().setColor(mColor);
} }
private int resolveColor(ImageView icon) { 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. // It also may lead to bugs where the icon isn't correctly greyed out.
boolean hadColorFilter = mNotificationHeader.getOriginalIconColor() boolean hadColorFilter = mNotificationHeader.getOriginalIconColor()
!= NotificationHeaderView.NO_COLOR; != 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) { getDozer().setImageDark(mIcon, dark, fade, delay, !hadColorFilter);
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);
} }
} }
@@ -316,22 +232,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
mNotificationHeader.setOnClickListener(expandable ? onClickListener : null); 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 @Override
public NotificationHeaderView getNotificationHeader() { public NotificationHeaderView getNotificationHeader() {
return mNotificationHeader; return mNotificationHeader;

View File

@@ -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);
}
}

View File

@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.notification; package com.android.systemui.statusbar.notification;
import android.animation.ValueAnimator;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.service.notification.StatusBarNotification; import android.service.notification.StatusBarNotification;
@@ -46,7 +45,8 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
private int mContentHeight; private int mContentHeight;
private int mMinHeightHint; private int mMinHeightHint;
protected NotificationTemplateViewWrapper(Context ctx, View view, ExpandableNotificationRow row) { protected NotificationTemplateViewWrapper(Context ctx, View view,
ExpandableNotificationRow row) {
super(ctx, view, row); super(ctx, view, row);
mTransformationHelper.setCustomTransformation( mTransformationHelper.setCustomTransformation(
new ViewTransformationHelper.CustomTransformation() { new ViewTransformationHelper.CustomTransformation() {
@@ -154,16 +154,20 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
// This also clears the existing types // This also clears the existing types
super.updateTransformedTypes(); super.updateTransformedTypes();
if (mTitle != null) { if (mTitle != null) {
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE, mTitle); mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
mTitle);
} }
if (mText != null) { if (mText != null) {
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT, mText); mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
mText);
} }
if (mPicture != null) { if (mPicture != null) {
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE, mPicture); mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE,
mPicture);
} }
if (mProgressBar != null) { 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; return;
} }
super.setDark(dark, fade, delay); super.setDark(dark, fade, delay);
setPictureGrayscale(dark, fade, delay); setPictureDark(dark, fade, delay);
setProgressBarDark(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) { private void fadeProgressDark(final ProgressBar target, final boolean dark, long delay) {
startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() { getDozer().startIntensityAnimation(animation -> {
@Override float t = (float) animation.getAnimatedValue();
public void onAnimationUpdate(ValueAnimator animation) { updateProgressDark(target, t);
float t = (float) animation.getAnimatedValue();
updateProgressDark(target, t);
}
}, dark, delay, null /* listener */); }, dark, delay, null /* listener */);
} }
@@ -207,13 +208,9 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
updateProgressDark(target, dark ? 1f : 0f); 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 (mPicture != null) {
if (fade) { getDozer().setImageDark(mPicture, dark, fade, delay, true /* useGrayscale */);
fadeGrayscale(mPicture, grayscale, delay);
} else {
updateGrayscale(mPicture, grayscale);
}
} }
} }

View File

@@ -16,24 +16,17 @@
package com.android.systemui.statusbar.notification; package com.android.systemui.statusbar.notification;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.service.notification.StatusBarNotification;
import android.support.v4.graphics.ColorUtils; import android.support.v4.graphics.ColorUtils;
import android.view.NotificationHeaderView; import android.view.NotificationHeaderView;
import android.view.View; 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.CrossFadeHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.TransformableView; 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 * 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 { public abstract class NotificationViewWrapper implements TransformableView {
protected final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
protected final View mView; protected final View mView;
protected final ExpandableNotificationRow mRow; protected final ExpandableNotificationRow mRow;
private final NotificationDozeHelper mDozer;
protected boolean mDark; protected boolean mDark;
private int mBackgroundColor = 0; private int mBackgroundColor = 0;
protected boolean mShouldInvertDark; protected boolean mShouldInvertDark;
protected boolean mDarkInitialized = false; protected boolean mDarkInitialized = false;
private boolean mForcedInvisible;
public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) { public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) { 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) { } else if (v instanceof NotificationHeaderView) {
return new NotificationHeaderViewWrapper(ctx, v, row); return new NotificationHeaderViewWrapper(ctx, v, row);
} else { } 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; mView = view;
mRow = row; 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; || 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. * Update the appearance of the expand button.
* *

View File

@@ -95,7 +95,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
private int mActualLayoutWidth = NO_VALUE; private int mActualLayoutWidth = NO_VALUE;
private float mActualPaddingEnd = NO_VALUE; private float mActualPaddingEnd = NO_VALUE;
private float mActualPaddingStart = NO_VALUE; private float mActualPaddingStart = NO_VALUE;
private boolean mCentered; private boolean mDark;
private boolean mChangingViewPositions; private boolean mChangingViewPositions;
private int mAddAnimationStartIndex = -1; private int mAddAnimationStartIndex = -1;
private int mCannedAnimationStartIndex = -1; private int mCannedAnimationStartIndex = -1;
@@ -183,6 +183,9 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, childIndex); mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, childIndex);
} }
} }
if (mDark && child instanceof StatusBarIconView) {
((StatusBarIconView) child).setDark(mDark, false, 0);
}
} }
@Override @Override
@@ -312,7 +315,8 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
numDots++; numDots++;
} }
} }
if (mCentered && translationX < getLayoutEnd()) { boolean center = mDark;
if (center && translationX < getLayoutEnd()) {
float delta = (getLayoutEnd() - translationX) / 2; float delta = (getLayoutEnd() - translationX) / 2;
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
View view = getChildAt(i); View view = getChildAt(i);
@@ -390,9 +394,15 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
mChangingViewPositions = changingViewPositions; mChangingViewPositions = changingViewPositions;
} }
public void setAmbient(boolean ambient) { public void setDark(boolean dark, boolean fade, long delay) {
mCentered = ambient; mDark = dark;
mDisallowNextAnimation = true; 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) { public IconState getIconState(StatusBarIconView icon) {

View File

@@ -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);
}
}
}