19c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek/* 29c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * Copyright (C) 2015 The Android Open Source Project 39c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * 49c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * Licensed under the Apache License, Version 2.0 (the "License"); 59c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * you may not use this file except in compliance with the License. 69c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * You may obtain a copy of the License at 79c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * 89c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * http://www.apache.org/licenses/LICENSE-2.0 99c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * 109c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * Unless required by applicable law or agreed to in writing, software 119c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * distributed under the License is distributed on an "AS IS" BASIS, 129c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * See the License for the specific language governing permissions and 149c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * limitations under the License 159c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek */ 169c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 170ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinekpackage com.android.systemui.statusbar.notification; 189c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 199c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.animation.Animator; 209c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.animation.AnimatorListenerAdapter; 219c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.animation.ValueAnimator; 229c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.content.Context; 239c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.graphics.Color; 249c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.graphics.ColorFilter; 259c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.graphics.ColorMatrixColorFilter; 269c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.graphics.PorterDuff; 279c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.graphics.PorterDuffColorFilter; 289c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.graphics.drawable.Drawable; 294ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinekimport android.service.notification.StatusBarNotification; 3075524417ac507597b19abb2a91389044bec682adAdrian Roosimport android.util.ArraySet; 319c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.view.NotificationHeaderView; 329c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.view.View; 330ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinekimport android.view.ViewGroup; 349c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport android.widget.ImageView; 359c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 369c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport com.android.systemui.R; 379c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport com.android.systemui.ViewInvertHelper; 387d1c63e66a2e19bf32249f52c56e563eae4c6819Selim Cinekimport com.android.systemui.statusbar.ExpandableNotificationRow; 390ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinekimport com.android.systemui.statusbar.TransformableView; 400ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinekimport com.android.systemui.statusbar.ViewTransformationHelper; 419c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekimport com.android.systemui.statusbar.phone.NotificationPanelView; 429c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 430ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinekimport java.util.Stack; 449c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 459c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek/** 469c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek * Wraps a notification header view. 479c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek */ 489c7712d45ccec56a80873a83e56a83f810624b43Selim Cinekpublic class NotificationHeaderViewWrapper extends NotificationViewWrapper { 499c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 509c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private final PorterDuffColorFilter mIconColorFilter = new PorterDuffColorFilter( 519c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 0, PorterDuff.Mode.SRC_ATOP); 529c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private final int mIconDarkAlpha; 539c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private final int mIconDarkColor = 0xffffffff; 549c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek protected final ViewInvertHelper mInvertHelper; 559c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 564ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek protected final ViewTransformationHelper mTransformationHelper; 574ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek 589c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek protected int mColor; 599c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private ImageView mIcon; 609c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 619c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private ImageView mExpandButton; 629c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private NotificationHeaderView mNotificationHeader; 639c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 647d1c63e66a2e19bf32249f52c56e563eae4c6819Selim Cinek protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) { 657d1c63e66a2e19bf32249f52c56e563eae4c6819Selim Cinek super(view, row); 669c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek mIconDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha); 679c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek mInvertHelper = new ViewInvertHelper(ctx, NotificationPanelView.DOZE_ANIMATION_DURATION); 684ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek mTransformationHelper = new ViewTransformationHelper(); 699c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek resolveHeaderViews(); 704ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek updateInvertHelper(); 719c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 729c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 739c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek protected void resolveHeaderViews() { 749c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek mIcon = (ImageView) mView.findViewById(com.android.internal.R.id.icon); 759c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek mExpandButton = (ImageView) mView.findViewById(com.android.internal.R.id.expand_button); 769c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek mColor = resolveColor(mExpandButton); 779c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek mNotificationHeader = (NotificationHeaderView) mView.findViewById( 789c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek com.android.internal.R.id.notification_header); 799c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 809c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 819c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private int resolveColor(ImageView icon) { 829c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek if (icon != null && icon.getDrawable() != null) { 839c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek ColorFilter filter = icon.getDrawable().getColorFilter(); 849c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek if (filter instanceof PorterDuffColorFilter) { 859c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek return ((PorterDuffColorFilter) filter).getColor(); 869c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 879c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 889c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek return 0; 899c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 909c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 919c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek @Override 924ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek public void notifyContentUpdated(StatusBarNotification notification) { 9319ba7050c3aaf47f431d33341de7399df776f559Selim Cinek super.notifyContentUpdated(notification); 9475524417ac507597b19abb2a91389044bec682adAdrian Roos 9575524417ac507597b19abb2a91389044bec682adAdrian Roos ArraySet<View> previousViews = mTransformationHelper.getAllTransformingViews(); 9675524417ac507597b19abb2a91389044bec682adAdrian Roos 979c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek // Reinspect the notification. 989c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek resolveHeaderViews(); 994ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek updateInvertHelper(); 1004ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek updateTransformedTypes(); 101646d2054dd76d7213ced8a73f2352f0d63f20043Selim Cinek addRemainingTransformTypes(); 1020ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek updateCropToPaddingForImageViews(); 10375524417ac507597b19abb2a91389044bec682adAdrian Roos 10475524417ac507597b19abb2a91389044bec682adAdrian Roos // We need to reset all views that are no longer transforming in case a view was previously 10575524417ac507597b19abb2a91389044bec682adAdrian Roos // transformed, but now we decided to transform its container instead. 10675524417ac507597b19abb2a91389044bec682adAdrian Roos ArraySet<View> currentViews = mTransformationHelper.getAllTransformingViews(); 10775524417ac507597b19abb2a91389044bec682adAdrian Roos for (int i = 0; i < previousViews.size(); i++) { 10875524417ac507597b19abb2a91389044bec682adAdrian Roos View view = previousViews.valueAt(i); 10975524417ac507597b19abb2a91389044bec682adAdrian Roos if (!currentViews.contains(view)) { 11075524417ac507597b19abb2a91389044bec682adAdrian Roos mTransformationHelper.resetTransformedView(view); 11175524417ac507597b19abb2a91389044bec682adAdrian Roos } 11275524417ac507597b19abb2a91389044bec682adAdrian Roos } 1130ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek } 1140ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek 1150ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek /** 116646d2054dd76d7213ced8a73f2352f0d63f20043Selim Cinek * Adds the remaining TransformTypes to the TransformHelper. This is done to make sure that each 117646d2054dd76d7213ced8a73f2352f0d63f20043Selim Cinek * child is faded automatically and doesn't have to be manually added. 118646d2054dd76d7213ced8a73f2352f0d63f20043Selim Cinek * The keys used for the views are the ids. 119646d2054dd76d7213ced8a73f2352f0d63f20043Selim Cinek */ 120646d2054dd76d7213ced8a73f2352f0d63f20043Selim Cinek private void addRemainingTransformTypes() { 121646d2054dd76d7213ced8a73f2352f0d63f20043Selim Cinek mTransformationHelper.addRemainingTransformTypes(mView); 122646d2054dd76d7213ced8a73f2352f0d63f20043Selim Cinek } 123646d2054dd76d7213ced8a73f2352f0d63f20043Selim Cinek 124646d2054dd76d7213ced8a73f2352f0d63f20043Selim Cinek /** 1250ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek * Since we are deactivating the clipping when transforming the ImageViews don't get clipped 1260ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek * anymore during these transitions. We can avoid that by using 1270ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek * {@link ImageView#setCropToPadding(boolean)} on all ImageViews. 1280ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek */ 1290ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek private void updateCropToPaddingForImageViews() { 1300ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek Stack<View> stack = new Stack<>(); 1310ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek stack.push(mView); 1320ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek while (!stack.isEmpty()) { 1330ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek View child = stack.pop(); 1340ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek if (child instanceof ImageView) { 1350ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek ((ImageView) child).setCropToPadding(true); 1360ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek } else if (child instanceof ViewGroup){ 1370ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek ViewGroup group = (ViewGroup) child; 1380ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek for (int i = 0; i < group.getChildCount(); i++) { 1390ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek stack.push(group.getChildAt(i)); 1400ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek } 1410ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek } 1420ffbda62e55ad390e05e6c3ff52e1378e420285cSelim Cinek } 1434ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek } 1444ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek 1454ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek protected void updateInvertHelper() { 1464ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek mInvertHelper.clearTargets(); 1474ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek for (int i = 0; i < mNotificationHeader.getChildCount(); i++) { 1484ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek View child = mNotificationHeader.getChildAt(i); 1494ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek if (child != mIcon) { 1504ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek mInvertHelper.addTarget(child); 1514ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek } 1524ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek } 1534ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek } 1544ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek 1554ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek protected void updateTransformedTypes() { 1564ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek mTransformationHelper.reset(); 1578f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_HEADER, 1588f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek mNotificationHeader); 1599c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 1609c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 1619c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek @Override 1629c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek public void setDark(boolean dark, boolean fade, long delay) { 163b88b98477ae725092c27dfe52f7fca3d4f29913eSelim Cinek if (dark == mDark && mDarkInitialized) { 16419ba7050c3aaf47f431d33341de7399df776f559Selim Cinek return; 16519ba7050c3aaf47f431d33341de7399df776f559Selim Cinek } 16619ba7050c3aaf47f431d33341de7399df776f559Selim Cinek super.setDark(dark, fade, delay); 1679c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek if (fade) { 1689c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek mInvertHelper.fade(dark, delay); 1699c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } else { 1709c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek mInvertHelper.update(dark); 1719c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 1727d1c63e66a2e19bf32249f52c56e563eae4c6819Selim Cinek if (mIcon != null && !mRow.isChildInGroup()) { 1737d1c63e66a2e19bf32249f52c56e563eae4c6819Selim Cinek // We don't update the color for children views / their icon is invisible anyway. 1747d1c63e66a2e19bf32249f52c56e563eae4c6819Selim Cinek // It also may lead to bugs where the icon isn't correctly greyed out. 1759c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek boolean hadColorFilter = mNotificationHeader.getOriginalIconColor() 1769c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek != NotificationHeaderView.NO_COLOR; 1779c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek if (fade) { 1789c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek if (hadColorFilter) { 1799c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek fadeIconColorFilter(mIcon, dark, delay); 1809c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek fadeIconAlpha(mIcon, dark, delay); 1819c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } else { 1829c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek fadeGrayscale(mIcon, dark, delay); 1839c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 1849c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } else { 1859c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek if (hadColorFilter) { 1869c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek updateIconColorFilter(mIcon, dark); 1879c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek updateIconAlpha(mIcon, dark); 1889c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } else { 1899c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek updateGrayscale(mIcon, dark); 1909c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 1919c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 1929c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 1939c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 1949c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 1959c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private void fadeIconColorFilter(final ImageView target, boolean dark, long delay) { 1969c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() { 1979c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek @Override 1989c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek public void onAnimationUpdate(ValueAnimator animation) { 1999c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek updateIconColorFilter(target, (Float) animation.getAnimatedValue()); 2009c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2019c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek }, dark, delay, null /* listener */); 2029c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2039c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 2049c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private void fadeIconAlpha(final ImageView target, boolean dark, long delay) { 2059c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() { 2069c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek @Override 2079c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek public void onAnimationUpdate(ValueAnimator animation) { 2089c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek float t = (float) animation.getAnimatedValue(); 2099c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek target.setImageAlpha((int) (255 * (1f - t) + mIconDarkAlpha * t)); 2109c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2119c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek }, dark, delay, null /* listener */); 2129c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2139c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 2149c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek protected void fadeGrayscale(final ImageView target, final boolean dark, long delay) { 2159c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() { 2169c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek @Override 2179c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek public void onAnimationUpdate(ValueAnimator animation) { 2189c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek updateGrayscaleMatrix((float) animation.getAnimatedValue()); 2199c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix)); 2209c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2219c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek }, dark, delay, new AnimatorListenerAdapter() { 2229c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek @Override 2239c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek public void onAnimationEnd(Animator animation) { 2249c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek if (!dark) { 2259c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek target.setColorFilter(null); 2269c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2279c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2289c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek }); 2299c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2309c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 2319c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private void updateIconColorFilter(ImageView target, boolean dark) { 2329c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek updateIconColorFilter(target, dark ? 1f : 0f); 2339c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2349c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 2359c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private void updateIconColorFilter(ImageView target, float intensity) { 2369c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek int color = interpolateColor(mColor, mIconDarkColor, intensity); 2379c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek mIconColorFilter.setColor(color); 2389c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek Drawable iconDrawable = target.getDrawable(); 2399c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 2409c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek // Also, the notification might have been modified during the animation, so background 2419c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek // might be null here. 2429c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek if (iconDrawable != null) { 2434aad455280dd19a3097e8fad3f68bfee1de30327Adrian Roos Drawable d = iconDrawable.mutate(); 2444aad455280dd19a3097e8fad3f68bfee1de30327Adrian Roos // DrawableContainer ignores the color filter if it's already set, so clear it first to 2454aad455280dd19a3097e8fad3f68bfee1de30327Adrian Roos // get it set and invalidated properly. 2464aad455280dd19a3097e8fad3f68bfee1de30327Adrian Roos d.setColorFilter(null); 2474aad455280dd19a3097e8fad3f68bfee1de30327Adrian Roos d.setColorFilter(mIconColorFilter); 2489c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2499c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2509c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 2519c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private void updateIconAlpha(ImageView target, boolean dark) { 2529c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek target.setImageAlpha(dark ? mIconDarkAlpha : 255); 2539c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2549c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 2559c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek protected void updateGrayscale(ImageView target, boolean dark) { 2569c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek if (dark) { 2579c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek updateGrayscaleMatrix(1f); 2589c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix)); 2599c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } else { 2609c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek target.setColorFilter(null); 2619c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2629c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2639c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 2649c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek @Override 2659c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) { 2669c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek mExpandButton.setVisibility(expandable ? View.VISIBLE : View.GONE); 2679c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek mNotificationHeader.setOnClickListener(expandable ? onClickListener : null); 2689c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2699c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 2709c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek private static int interpolateColor(int source, int target, float t) { 2719c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek int aSource = Color.alpha(source); 2729c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek int rSource = Color.red(source); 2739c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek int gSource = Color.green(source); 2749c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek int bSource = Color.blue(source); 2759c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek int aTarget = Color.alpha(target); 2769c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek int rTarget = Color.red(target); 2779c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek int gTarget = Color.green(target); 2789c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek int bTarget = Color.blue(target); 2799c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek return Color.argb( 2809c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek (int) (aSource * (1f - t) + aTarget * t), 2819c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek (int) (rSource * (1f - t) + rTarget * t), 2829c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek (int) (gSource * (1f - t) + gTarget * t), 2839c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek (int) (bSource * (1f - t) + bTarget * t)); 2849c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2859c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek 2869c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek @Override 2879c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek public NotificationHeaderView getNotificationHeader() { 2889c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek return mNotificationHeader; 2899c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek } 2904ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek 2914ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek @Override 2924ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek public TransformState getCurrentState(int fadingView) { 2934ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek return mTransformationHelper.getCurrentState(fadingView); 2944ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek } 2954ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek 2964ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek @Override 2974ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek public void transformTo(TransformableView notification, Runnable endRunnable) { 2984ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek mTransformationHelper.transformTo(notification, endRunnable); 2994ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek } 3004ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek 3014ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek @Override 3028f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek public void transformTo(TransformableView notification, float transformationAmount) { 3038f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek mTransformationHelper.transformTo(notification, transformationAmount); 3048f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek } 3058f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek 3068f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek @Override 3074ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek public void transformFrom(TransformableView notification) { 3084ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek mTransformationHelper.transformFrom(notification); 3094ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek } 3104ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek 3114ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek @Override 3128f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek public void transformFrom(TransformableView notification, float transformationAmount) { 3138f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek mTransformationHelper.transformFrom(notification, transformationAmount); 3148f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek } 3158f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek 3168f2f6a67fad7aed720e33a6629cb65d368ebfb80Selim Cinek @Override 3174ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek public void setVisible(boolean visible) { 3184ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek super.setVisible(visible); 3194ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek mTransformationHelper.setVisible(visible); 3204ffd63611a0d516c9988b37e9c06e6f8390c2a2fSelim Cinek } 3219c7712d45ccec56a80873a83e56a83f810624b43Selim Cinek} 322