blob: ade27f9f3ad2d4a8c6aff103fd817b522f38cfb4 [file] [log] [blame]
Selim Cinek9c7712d2015-12-08 19:19:48 -08001/*
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 Cinek0ffbda62016-01-01 20:29:12 +010017package com.android.systemui.statusbar.notification;
Selim Cinek9c7712d2015-12-08 19:19:48 -080018
felkachang08579552018-05-24 15:38:04 +080019import static com.android.systemui.statusbar.ExpandableNotificationRow
20 .DEFAULT_HEADER_VISIBLE_AMOUNT;
Selim Cinek2325aa22018-05-04 18:05:33 -070021import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
22
Selim Cinek414ad332017-02-24 19:06:12 -080023import android.app.Notification;
Selim Cinek9c7712d2015-12-08 19:19:48 -080024import android.content.Context;
Adrian Roos75524412016-06-21 11:56:57 -070025import android.util.ArraySet;
Selim Cinek9c7712d2015-12-08 19:19:48 -080026import android.view.NotificationHeaderView;
27import android.view.View;
Selim Cinek0ffbda62016-01-01 20:29:12 +010028import android.view.ViewGroup;
Selim Cinek5be6f332017-01-19 11:54:04 -080029import android.view.animation.Interpolator;
30import android.view.animation.PathInterpolator;
Selim Cinek9c7712d2015-12-08 19:19:48 -080031import android.widget.ImageView;
Selim Cinek6743c0b2017-01-18 18:24:01 -080032import android.widget.TextView;
Selim Cinek9c7712d2015-12-08 19:19:48 -080033
Selim Cinek69e76f92017-04-05 17:06:02 -070034import com.android.internal.widget.NotificationExpandButton;
Selim Cinek5be6f332017-01-19 11:54:04 -080035import com.android.systemui.Interpolators;
Anthony Chen0f6e96c2017-04-07 15:48:17 -070036import com.android.systemui.R;
Selim Cinek7d1c63e2016-04-21 15:26:10 -070037import com.android.systemui.statusbar.ExpandableNotificationRow;
Selim Cinek0ffbda62016-01-01 20:29:12 +010038import com.android.systemui.statusbar.TransformableView;
39import com.android.systemui.statusbar.ViewTransformationHelper;
Selim Cinek9c7712d2015-12-08 19:19:48 -080040
Selim Cinek0ffbda62016-01-01 20:29:12 +010041import java.util.Stack;
Selim Cinek9c7712d2015-12-08 19:19:48 -080042
43/**
44 * Wraps a notification header view.
45 */
46public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
47
Selim Cinek5be6f332017-01-19 11:54:04 -080048 private static final Interpolator LOW_PRIORITY_HEADER_CLOSE
49 = new PathInterpolator(0.4f, 0f, 0.7f, 1f);
Selim Cinek9c7712d2015-12-08 19:19:48 -080050
Selim Cinek4ffd6362015-12-29 15:12:23 +010051 protected final ViewTransformationHelper mTransformationHelper;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080052 private final int mTranslationForHeader;
Selim Cinek4ffd6362015-12-29 15:12:23 +010053
Selim Cinek9c7712d2015-12-08 19:19:48 -080054 protected int mColor;
55 private ImageView mIcon;
56
Selim Cinek69e76f92017-04-05 17:06:02 -070057 private NotificationExpandButton mExpandButton;
Selim Cinek9c7712d2015-12-08 19:19:48 -080058 private NotificationHeaderView mNotificationHeader;
Selim Cinek6743c0b2017-01-18 18:24:01 -080059 private TextView mHeaderText;
60 private ImageView mWorkProfileImage;
61 private boolean mIsLowPriority;
Selim Cinek414ad332017-02-24 19:06:12 -080062 private boolean mTransformLowPriorityTitle;
Anthony Chen0f6e96c2017-04-07 15:48:17 -070063 private boolean mShowExpandButtonAtEnd;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080064 protected float mHeaderTranslation;
Selim Cinek9c7712d2015-12-08 19:19:48 -080065
Selim Cinek7d1c63e2016-04-21 15:26:10 -070066 protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
Adrian Roos7bcf6d32017-04-04 16:44:25 -070067 super(ctx, view, row);
Anthony Chen0f6e96c2017-04-07 15:48:17 -070068 mShowExpandButtonAtEnd = ctx.getResources().getBoolean(
69 R.bool.config_showNotificationExpandButtonAtEnd);
Selim Cinek4ffd6362015-12-29 15:12:23 +010070 mTransformationHelper = new ViewTransformationHelper();
Selim Cinek5be6f332017-01-19 11:54:04 -080071
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 Cinek414ad332017-02-24 19:06:12 -080094 return mIsLowPriority && mTransformLowPriorityTitle;
Selim Cinek5be6f332017-01-19 11:54:04 -080095 }
96 }, TRANSFORMING_VIEW_TITLE);
Selim Cinek9c7712d2015-12-08 19:19:48 -080097 resolveHeaderViews();
Julia Reynoldsb5867452018-02-28 16:31:35 -050098 addAppOpsOnClickListener(row);
Selim Cinekaa9db1f2018-02-27 17:35:47 -080099 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 Cinek9c7712d2015-12-08 19:19:48 -0800103 }
104
105 protected void resolveHeaderViews() {
Selim Cinek69e76f92017-04-05 17:06:02 -0700106 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 Cinek69e76f92017-04-05 17:06:02 -0700109 mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
Selim Cinek69e76f92017-04-05 17:06:02 -0700110 mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
Anthony Chen0f6e96c2017-04-07 15:48:17 -0700111 mNotificationHeader.setShowExpandButtonAtEnd(mShowExpandButtonAtEnd);
Selim Cinekc7f5a822018-03-20 19:32:06 -0700112 mColor = mNotificationHeader.getOriginalIconColor();
Selim Cinek9c7712d2015-12-08 19:19:48 -0800113 }
114
Julia Reynoldsb5867452018-02-28 16:31:35 -0500115 private void addAppOpsOnClickListener(ExpandableNotificationRow row) {
116 mNotificationHeader.setAppOpsOnClickListener(row.getAppOpsOnClickListener());
117 }
118
Selim Cinek9c7712d2015-12-08 19:19:48 -0800119 @Override
Selim Cinek131f1a42017-06-05 17:50:19 -0700120 public void onContentUpdated(ExpandableNotificationRow row) {
121 super.onContentUpdated(row);
Selim Cinek414ad332017-02-24 19:06:12 -0800122 mIsLowPriority = row.isLowPriority();
123 mTransformLowPriorityTitle = !row.isChildInGroup() && !row.isSummaryWithChildren();
Adrian Roos75524412016-06-21 11:56:57 -0700124 ArraySet<View> previousViews = mTransformationHelper.getAllTransformingViews();
125
Selim Cinek9c7712d2015-12-08 19:19:48 -0800126 // Reinspect the notification.
127 resolveHeaderViews();
felkachang08579552018-05-24 15:38:04 +0800128 if (row.getHeaderVisibleAmount() != DEFAULT_HEADER_VISIBLE_AMOUNT) {
129 setHeaderVisibleAmount(row.getHeaderVisibleAmount());
130 }
Selim Cinek4ffd6362015-12-29 15:12:23 +0100131 updateTransformedTypes();
Selim Cinek646d2052016-01-03 14:42:02 +0800132 addRemainingTransformTypes();
Selim Cinek0ffbda62016-01-01 20:29:12 +0100133 updateCropToPaddingForImageViews();
Selim Cinek414ad332017-02-24 19:06:12 -0800134 Notification notification = row.getStatusBarNotification().getNotification();
135 mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
Selim Cinek6743c0b2017-01-18 18:24:01 -0800136 // The work profile image is always the same lets just set the icon tag for it not to
137 // animate
Selim Cinek414ad332017-02-24 19:06:12 -0800138 mWorkProfileImage.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
Adrian Roos75524412016-06-21 11:56:57 -0700139
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 Cinek0ffbda62016-01-01 20:29:12 +0100149 }
150
151 /**
Selim Cinek646d2052016-01-03 14:42:02 +0800152 * 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 Cinek0ffbda62016-01-01 20:29:12 +0100161 * 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 Cinek4ffd6362015-12-29 15:12:23 +0100179 }
180
Selim Cinek4ffd6362015-12-29 15:12:23 +0100181 protected void updateTransformedTypes() {
182 mTransformationHelper.reset();
Selim Cinek6743c0b2017-01-18 18:24:01 -0800183 mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_ICON, mIcon);
184 if (mIsLowPriority) {
185 mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
186 mHeaderText);
187 }
Selim Cinek9c7712d2015-12-08 19:19:48 -0800188 }
189
190 @Override
Selim Cinek9c7712d2015-12-08 19:19:48 -0800191 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 Cinek9c7712d2015-12-08 19:19:48 -0800196 @Override
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800197 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 Cinek9c7712d2015-12-08 19:19:48 -0800210 public NotificationHeaderView getNotificationHeader() {
211 return mNotificationHeader;
212 }
Selim Cinek4ffd6362015-12-29 15:12:23 +0100213
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 Cinek8f2f6a62016-02-23 19:56:31 -0800225 public void transformTo(TransformableView notification, float transformationAmount) {
226 mTransformationHelper.transformTo(notification, transformationAmount);
227 }
228
229 @Override
Selim Cinek4ffd6362015-12-29 15:12:23 +0100230 public void transformFrom(TransformableView notification) {
231 mTransformationHelper.transformFrom(notification);
232 }
233
234 @Override
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800235 public void transformFrom(TransformableView notification, float transformationAmount) {
236 mTransformationHelper.transformFrom(notification, transformationAmount);
237 }
238
239 @Override
Selim Cinek414ad332017-02-24 19:06:12 -0800240 public void setIsChildInGroup(boolean isChildInGroup) {
241 super.setIsChildInGroup(isChildInGroup);
242 mTransformLowPriorityTitle = !isChildInGroup;
243 }
244
245 @Override
Selim Cinek4ffd6362015-12-29 15:12:23 +0100246 public void setVisible(boolean visible) {
247 super.setVisible(visible);
248 mTransformationHelper.setVisible(visible);
249 }
Selim Cinek9c7712d2015-12-08 19:19:48 -0800250}