Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2015 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License |
| 15 | */ |
| 16 | |
Selim Cinek | 0ffbda6 | 2016-01-01 20:29:12 +0100 | [diff] [blame] | 17 | package com.android.systemui.statusbar.notification; |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 18 | |
felkachang | 0857955 | 2018-05-24 15:38:04 +0800 | [diff] [blame] | 19 | import static com.android.systemui.statusbar.ExpandableNotificationRow |
| 20 | .DEFAULT_HEADER_VISIBLE_AMOUNT; |
Selim Cinek | 2325aa2 | 2018-05-04 18:05:33 -0700 | [diff] [blame] | 21 | import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y; |
| 22 | |
Selim Cinek | 414ad33 | 2017-02-24 19:06:12 -0800 | [diff] [blame] | 23 | import android.app.Notification; |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 24 | import android.content.Context; |
Adrian Roos | 7552441 | 2016-06-21 11:56:57 -0700 | [diff] [blame] | 25 | import android.util.ArraySet; |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 26 | import android.view.NotificationHeaderView; |
| 27 | import android.view.View; |
Selim Cinek | 0ffbda6 | 2016-01-01 20:29:12 +0100 | [diff] [blame] | 28 | import android.view.ViewGroup; |
Selim Cinek | 5be6f33 | 2017-01-19 11:54:04 -0800 | [diff] [blame] | 29 | import android.view.animation.Interpolator; |
| 30 | import android.view.animation.PathInterpolator; |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 31 | import android.widget.ImageView; |
Selim Cinek | 6743c0b | 2017-01-18 18:24:01 -0800 | [diff] [blame] | 32 | import android.widget.TextView; |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 33 | |
Selim Cinek | 69e76f9 | 2017-04-05 17:06:02 -0700 | [diff] [blame] | 34 | import com.android.internal.widget.NotificationExpandButton; |
Selim Cinek | 5be6f33 | 2017-01-19 11:54:04 -0800 | [diff] [blame] | 35 | import com.android.systemui.Interpolators; |
Anthony Chen | 0f6e96c | 2017-04-07 15:48:17 -0700 | [diff] [blame] | 36 | import com.android.systemui.R; |
Selim Cinek | 7d1c63e | 2016-04-21 15:26:10 -0700 | [diff] [blame] | 37 | import com.android.systemui.statusbar.ExpandableNotificationRow; |
Selim Cinek | 0ffbda6 | 2016-01-01 20:29:12 +0100 | [diff] [blame] | 38 | import com.android.systemui.statusbar.TransformableView; |
| 39 | import com.android.systemui.statusbar.ViewTransformationHelper; |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 40 | |
Selim Cinek | 0ffbda6 | 2016-01-01 20:29:12 +0100 | [diff] [blame] | 41 | import java.util.Stack; |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 42 | |
| 43 | /** |
| 44 | * Wraps a notification header view. |
| 45 | */ |
| 46 | public class NotificationHeaderViewWrapper extends NotificationViewWrapper { |
| 47 | |
Selim Cinek | 5be6f33 | 2017-01-19 11:54:04 -0800 | [diff] [blame] | 48 | private static final Interpolator LOW_PRIORITY_HEADER_CLOSE |
| 49 | = new PathInterpolator(0.4f, 0f, 0.7f, 1f); |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 50 | |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 51 | protected final ViewTransformationHelper mTransformationHelper; |
Selim Cinek | aa9db1f | 2018-02-27 17:35:47 -0800 | [diff] [blame] | 52 | private final int mTranslationForHeader; |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 53 | |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 54 | protected int mColor; |
| 55 | private ImageView mIcon; |
| 56 | |
Selim Cinek | 69e76f9 | 2017-04-05 17:06:02 -0700 | [diff] [blame] | 57 | private NotificationExpandButton mExpandButton; |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 58 | private NotificationHeaderView mNotificationHeader; |
Selim Cinek | 6743c0b | 2017-01-18 18:24:01 -0800 | [diff] [blame] | 59 | private TextView mHeaderText; |
| 60 | private ImageView mWorkProfileImage; |
| 61 | private boolean mIsLowPriority; |
Selim Cinek | 414ad33 | 2017-02-24 19:06:12 -0800 | [diff] [blame] | 62 | private boolean mTransformLowPriorityTitle; |
Anthony Chen | 0f6e96c | 2017-04-07 15:48:17 -0700 | [diff] [blame] | 63 | private boolean mShowExpandButtonAtEnd; |
Selim Cinek | aa9db1f | 2018-02-27 17:35:47 -0800 | [diff] [blame] | 64 | protected float mHeaderTranslation; |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 65 | |
Selim Cinek | 7d1c63e | 2016-04-21 15:26:10 -0700 | [diff] [blame] | 66 | protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) { |
Adrian Roos | 7bcf6d3 | 2017-04-04 16:44:25 -0700 | [diff] [blame] | 67 | super(ctx, view, row); |
Anthony Chen | 0f6e96c | 2017-04-07 15:48:17 -0700 | [diff] [blame] | 68 | mShowExpandButtonAtEnd = ctx.getResources().getBoolean( |
| 69 | R.bool.config_showNotificationExpandButtonAtEnd); |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 70 | mTransformationHelper = new ViewTransformationHelper(); |
Selim Cinek | 5be6f33 | 2017-01-19 11:54:04 -0800 | [diff] [blame] | 71 | |
| 72 | // we want to avoid that the header clashes with the other text when transforming |
| 73 | // low-priority |
| 74 | mTransformationHelper.setCustomTransformation( |
| 75 | new CustomInterpolatorTransformation(TRANSFORMING_VIEW_TITLE) { |
| 76 | |
| 77 | @Override |
| 78 | public Interpolator getCustomInterpolator(int interpolationType, |
| 79 | boolean isFrom) { |
| 80 | boolean isLowPriority = mView instanceof NotificationHeaderView; |
| 81 | if (interpolationType == TRANSFORM_Y) { |
| 82 | if (isLowPriority && !isFrom |
| 83 | || !isLowPriority && isFrom) { |
| 84 | return Interpolators.LINEAR_OUT_SLOW_IN; |
| 85 | } else { |
| 86 | return LOW_PRIORITY_HEADER_CLOSE; |
| 87 | } |
| 88 | } |
| 89 | return null; |
| 90 | } |
| 91 | |
| 92 | @Override |
| 93 | protected boolean hasCustomTransformation() { |
Selim Cinek | 414ad33 | 2017-02-24 19:06:12 -0800 | [diff] [blame] | 94 | return mIsLowPriority && mTransformLowPriorityTitle; |
Selim Cinek | 5be6f33 | 2017-01-19 11:54:04 -0800 | [diff] [blame] | 95 | } |
| 96 | }, TRANSFORMING_VIEW_TITLE); |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 97 | resolveHeaderViews(); |
Julia Reynolds | b586745 | 2018-02-28 16:31:35 -0500 | [diff] [blame] | 98 | addAppOpsOnClickListener(row); |
Selim Cinek | aa9db1f | 2018-02-27 17:35:47 -0800 | [diff] [blame] | 99 | mTranslationForHeader = ctx.getResources().getDimensionPixelSize( |
| 100 | com.android.internal.R.dimen.notification_content_margin) |
| 101 | - ctx.getResources().getDimensionPixelSize( |
| 102 | com.android.internal.R.dimen.notification_content_margin_top); |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | protected void resolveHeaderViews() { |
Selim Cinek | 69e76f9 | 2017-04-05 17:06:02 -0700 | [diff] [blame] | 106 | mIcon = mView.findViewById(com.android.internal.R.id.icon); |
| 107 | mHeaderText = mView.findViewById(com.android.internal.R.id.header_text); |
| 108 | mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button); |
Selim Cinek | 69e76f9 | 2017-04-05 17:06:02 -0700 | [diff] [blame] | 109 | mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge); |
Selim Cinek | 69e76f9 | 2017-04-05 17:06:02 -0700 | [diff] [blame] | 110 | mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header); |
Anthony Chen | 0f6e96c | 2017-04-07 15:48:17 -0700 | [diff] [blame] | 111 | mNotificationHeader.setShowExpandButtonAtEnd(mShowExpandButtonAtEnd); |
Selim Cinek | c7f5a82 | 2018-03-20 19:32:06 -0700 | [diff] [blame] | 112 | mColor = mNotificationHeader.getOriginalIconColor(); |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 113 | } |
| 114 | |
Julia Reynolds | b586745 | 2018-02-28 16:31:35 -0500 | [diff] [blame] | 115 | private void addAppOpsOnClickListener(ExpandableNotificationRow row) { |
| 116 | mNotificationHeader.setAppOpsOnClickListener(row.getAppOpsOnClickListener()); |
| 117 | } |
| 118 | |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 119 | @Override |
Selim Cinek | 131f1a4 | 2017-06-05 17:50:19 -0700 | [diff] [blame] | 120 | public void onContentUpdated(ExpandableNotificationRow row) { |
| 121 | super.onContentUpdated(row); |
Selim Cinek | 414ad33 | 2017-02-24 19:06:12 -0800 | [diff] [blame] | 122 | mIsLowPriority = row.isLowPriority(); |
| 123 | mTransformLowPriorityTitle = !row.isChildInGroup() && !row.isSummaryWithChildren(); |
Adrian Roos | 7552441 | 2016-06-21 11:56:57 -0700 | [diff] [blame] | 124 | ArraySet<View> previousViews = mTransformationHelper.getAllTransformingViews(); |
| 125 | |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 126 | // Reinspect the notification. |
| 127 | resolveHeaderViews(); |
felkachang | 0857955 | 2018-05-24 15:38:04 +0800 | [diff] [blame] | 128 | if (row.getHeaderVisibleAmount() != DEFAULT_HEADER_VISIBLE_AMOUNT) { |
| 129 | setHeaderVisibleAmount(row.getHeaderVisibleAmount()); |
| 130 | } |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 131 | updateTransformedTypes(); |
Selim Cinek | 646d205 | 2016-01-03 14:42:02 +0800 | [diff] [blame] | 132 | addRemainingTransformTypes(); |
Selim Cinek | 0ffbda6 | 2016-01-01 20:29:12 +0100 | [diff] [blame] | 133 | updateCropToPaddingForImageViews(); |
Selim Cinek | 414ad33 | 2017-02-24 19:06:12 -0800 | [diff] [blame] | 134 | Notification notification = row.getStatusBarNotification().getNotification(); |
| 135 | mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon()); |
Selim Cinek | 6743c0b | 2017-01-18 18:24:01 -0800 | [diff] [blame] | 136 | // The work profile image is always the same lets just set the icon tag for it not to |
| 137 | // animate |
Selim Cinek | 414ad33 | 2017-02-24 19:06:12 -0800 | [diff] [blame] | 138 | mWorkProfileImage.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon()); |
Adrian Roos | 7552441 | 2016-06-21 11:56:57 -0700 | [diff] [blame] | 139 | |
| 140 | // We need to reset all views that are no longer transforming in case a view was previously |
| 141 | // transformed, but now we decided to transform its container instead. |
| 142 | ArraySet<View> currentViews = mTransformationHelper.getAllTransformingViews(); |
| 143 | for (int i = 0; i < previousViews.size(); i++) { |
| 144 | View view = previousViews.valueAt(i); |
| 145 | if (!currentViews.contains(view)) { |
| 146 | mTransformationHelper.resetTransformedView(view); |
| 147 | } |
| 148 | } |
Selim Cinek | 0ffbda6 | 2016-01-01 20:29:12 +0100 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | /** |
Selim Cinek | 646d205 | 2016-01-03 14:42:02 +0800 | [diff] [blame] | 152 | * Adds the remaining TransformTypes to the TransformHelper. This is done to make sure that each |
| 153 | * child is faded automatically and doesn't have to be manually added. |
| 154 | * The keys used for the views are the ids. |
| 155 | */ |
| 156 | private void addRemainingTransformTypes() { |
| 157 | mTransformationHelper.addRemainingTransformTypes(mView); |
| 158 | } |
| 159 | |
| 160 | /** |
Selim Cinek | 0ffbda6 | 2016-01-01 20:29:12 +0100 | [diff] [blame] | 161 | * Since we are deactivating the clipping when transforming the ImageViews don't get clipped |
| 162 | * anymore during these transitions. We can avoid that by using |
| 163 | * {@link ImageView#setCropToPadding(boolean)} on all ImageViews. |
| 164 | */ |
| 165 | private void updateCropToPaddingForImageViews() { |
| 166 | Stack<View> stack = new Stack<>(); |
| 167 | stack.push(mView); |
| 168 | while (!stack.isEmpty()) { |
| 169 | View child = stack.pop(); |
| 170 | if (child instanceof ImageView) { |
| 171 | ((ImageView) child).setCropToPadding(true); |
| 172 | } else if (child instanceof ViewGroup){ |
| 173 | ViewGroup group = (ViewGroup) child; |
| 174 | for (int i = 0; i < group.getChildCount(); i++) { |
| 175 | stack.push(group.getChildAt(i)); |
| 176 | } |
| 177 | } |
| 178 | } |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 179 | } |
| 180 | |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 181 | protected void updateTransformedTypes() { |
| 182 | mTransformationHelper.reset(); |
Selim Cinek | 6743c0b | 2017-01-18 18:24:01 -0800 | [diff] [blame] | 183 | mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_ICON, mIcon); |
| 184 | if (mIsLowPriority) { |
| 185 | mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE, |
| 186 | mHeaderText); |
| 187 | } |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | @Override |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 191 | public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) { |
| 192 | mExpandButton.setVisibility(expandable ? View.VISIBLE : View.GONE); |
| 193 | mNotificationHeader.setOnClickListener(expandable ? onClickListener : null); |
| 194 | } |
| 195 | |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 196 | @Override |
Selim Cinek | aa9db1f | 2018-02-27 17:35:47 -0800 | [diff] [blame] | 197 | public void setHeaderVisibleAmount(float headerVisibleAmount) { |
| 198 | super.setHeaderVisibleAmount(headerVisibleAmount); |
| 199 | mNotificationHeader.setAlpha(headerVisibleAmount); |
| 200 | mHeaderTranslation = (1.0f - headerVisibleAmount) * mTranslationForHeader; |
| 201 | mView.setTranslationY(mHeaderTranslation); |
| 202 | } |
| 203 | |
| 204 | @Override |
| 205 | public int getHeaderTranslation() { |
| 206 | return (int) mHeaderTranslation; |
| 207 | } |
| 208 | |
| 209 | @Override |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 210 | public NotificationHeaderView getNotificationHeader() { |
| 211 | return mNotificationHeader; |
| 212 | } |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 213 | |
| 214 | @Override |
| 215 | public TransformState getCurrentState(int fadingView) { |
| 216 | return mTransformationHelper.getCurrentState(fadingView); |
| 217 | } |
| 218 | |
| 219 | @Override |
| 220 | public void transformTo(TransformableView notification, Runnable endRunnable) { |
| 221 | mTransformationHelper.transformTo(notification, endRunnable); |
| 222 | } |
| 223 | |
| 224 | @Override |
Selim Cinek | 8f2f6a6 | 2016-02-23 19:56:31 -0800 | [diff] [blame] | 225 | public void transformTo(TransformableView notification, float transformationAmount) { |
| 226 | mTransformationHelper.transformTo(notification, transformationAmount); |
| 227 | } |
| 228 | |
| 229 | @Override |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 230 | public void transformFrom(TransformableView notification) { |
| 231 | mTransformationHelper.transformFrom(notification); |
| 232 | } |
| 233 | |
| 234 | @Override |
Selim Cinek | 8f2f6a6 | 2016-02-23 19:56:31 -0800 | [diff] [blame] | 235 | public void transformFrom(TransformableView notification, float transformationAmount) { |
| 236 | mTransformationHelper.transformFrom(notification, transformationAmount); |
| 237 | } |
| 238 | |
| 239 | @Override |
Selim Cinek | 414ad33 | 2017-02-24 19:06:12 -0800 | [diff] [blame] | 240 | public void setIsChildInGroup(boolean isChildInGroup) { |
| 241 | super.setIsChildInGroup(isChildInGroup); |
| 242 | mTransformLowPriorityTitle = !isChildInGroup; |
| 243 | } |
| 244 | |
| 245 | @Override |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 246 | public void setVisible(boolean visible) { |
| 247 | super.setVisible(visible); |
| 248 | mTransformationHelper.setVisible(visible); |
| 249 | } |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 250 | } |