Jorim Jaggi | 4e857f4 | 2014-11-17 19:14:04 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2014 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 | |
Rohan Shah | 20790b8 | 2018-07-02 17:21:04 -0700 | [diff] [blame] | 17 | package com.android.systemui.statusbar.notification.row.wrapper; |
Jorim Jaggi | 4e857f4 | 2014-11-17 19:14:04 +0100 | [diff] [blame] | 18 | |
Selim Cinek | 4b259a1 | 2019-05-09 19:10:51 -0700 | [diff] [blame] | 19 | import static com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.DEFAULT_HEADER_VISIBLE_AMOUNT; |
| 20 | |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 21 | import android.app.PendingIntent; |
Jorim Jaggi | 4e857f4 | 2014-11-17 19:14:04 +0100 | [diff] [blame] | 22 | import android.content.Context; |
Selim Cinek | 019d71e | 2018-04-19 10:24:39 +0800 | [diff] [blame] | 23 | import android.content.res.ColorStateList; |
Jorim Jaggi | 4e857f4 | 2014-11-17 19:14:04 +0100 | [diff] [blame] | 24 | import android.graphics.Color; |
Selim Cinek | 019d71e | 2018-04-19 10:24:39 +0800 | [diff] [blame] | 25 | import android.graphics.PorterDuffColorFilter; |
Selim Cinek | 5d6ef8d | 2017-05-18 22:16:00 -0700 | [diff] [blame] | 26 | import android.graphics.Rect; |
Selim Cinek | 019d71e | 2018-04-19 10:24:39 +0800 | [diff] [blame] | 27 | import android.graphics.drawable.Drawable; |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 28 | import android.service.notification.StatusBarNotification; |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 29 | import android.util.ArraySet; |
Jorim Jaggi | 4e857f4 | 2014-11-17 19:14:04 +0100 | [diff] [blame] | 30 | import android.view.View; |
Selim Cinek | 019d71e | 2018-04-19 10:24:39 +0800 | [diff] [blame] | 31 | import android.widget.Button; |
Jorim Jaggi | 4e857f4 | 2014-11-17 19:14:04 +0100 | [diff] [blame] | 32 | import android.widget.ImageView; |
Selim Cinek | 75fe38c | 2015-11-20 12:47:59 -0800 | [diff] [blame] | 33 | import android.widget.ProgressBar; |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 34 | import android.widget.TextView; |
| 35 | |
Lucas Dupin | a291d19 | 2018-06-07 13:59:42 -0700 | [diff] [blame] | 36 | import com.android.internal.util.ContrastColorUtil; |
Selim Cinek | 396caca | 2018-04-10 17:46:46 -0700 | [diff] [blame] | 37 | import com.android.internal.widget.NotificationActionListLayout; |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 38 | import com.android.systemui.Dependency; |
Selim Cinek | bee4e07 | 2018-05-21 22:06:43 -0700 | [diff] [blame] | 39 | import com.android.systemui.R; |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 40 | import com.android.systemui.UiOffloadThread; |
Selim Cinek | fd3e262 | 2016-01-12 16:02:42 -0800 | [diff] [blame] | 41 | import com.android.systemui.statusbar.CrossFadeHelper; |
Gus Prevas | ab33679 | 2018-11-14 13:52:20 -0500 | [diff] [blame] | 42 | import com.android.systemui.statusbar.TransformableView; |
| 43 | import com.android.systemui.statusbar.ViewTransformationHelper; |
Rohan Shah | 20790b8 | 2018-07-02 17:21:04 -0700 | [diff] [blame] | 44 | import com.android.systemui.statusbar.notification.ImageTransformState; |
| 45 | import com.android.systemui.statusbar.notification.TransformState; |
| 46 | import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; |
Rohan Shah | 20790b8 | 2018-07-02 17:21:04 -0700 | [diff] [blame] | 47 | import com.android.systemui.statusbar.notification.row.HybridNotificationView; |
Selim Cinek | 65b2e7c | 2015-10-26 14:11:31 -0700 | [diff] [blame] | 48 | |
Jorim Jaggi | 4e857f4 | 2014-11-17 19:14:04 +0100 | [diff] [blame] | 49 | /** |
| 50 | * Wraps a notification view inflated from a template. |
| 51 | */ |
Selim Cinek | 9c7712d | 2015-12-08 19:19:48 -0800 | [diff] [blame] | 52 | public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapper { |
Jorim Jaggi | 4e857f4 | 2014-11-17 19:14:04 +0100 | [diff] [blame] | 53 | |
Selim Cinek | 4b259a1 | 2019-05-09 19:10:51 -0700 | [diff] [blame] | 54 | private final int mTranslationForHeader; |
Jorim Jaggi | dacc924 | 2014-12-08 19:21:26 +0100 | [diff] [blame] | 55 | protected ImageView mPicture; |
Selim Cinek | 75fe38c | 2015-11-20 12:47:59 -0800 | [diff] [blame] | 56 | private ProgressBar mProgressBar; |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 57 | private TextView mTitle; |
| 58 | private TextView mText; |
Selim Cinek | e62255c | 2017-09-28 18:23:23 -0700 | [diff] [blame] | 59 | protected View mActionsContainer; |
Selim Cinek | 019d71e | 2018-04-19 10:24:39 +0800 | [diff] [blame] | 60 | private ImageView mReplyAction; |
Selim Cinek | 5d6ef8d | 2017-05-18 22:16:00 -0700 | [diff] [blame] | 61 | private Rect mTmpRect = new Rect(); |
Adrian Roos | 181385c | 2016-05-05 17:45:44 -0400 | [diff] [blame] | 62 | |
| 63 | private int mContentHeight; |
| 64 | private int mMinHeightHint; |
Selim Cinek | 396caca | 2018-04-10 17:46:46 -0700 | [diff] [blame] | 65 | private NotificationActionListLayout mActions; |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 66 | private ArraySet<PendingIntent> mCancelledPendingIntents = new ArraySet<>(); |
| 67 | private UiOffloadThread mUiOffloadThread; |
Selim Cinek | bee4e07 | 2018-05-21 22:06:43 -0700 | [diff] [blame] | 68 | private View mRemoteInputHistory; |
Selim Cinek | 4b259a1 | 2019-05-09 19:10:51 -0700 | [diff] [blame] | 69 | private float mHeaderTranslation; |
Jorim Jaggi | 92df1f2 | 2014-12-16 19:44:41 +0100 | [diff] [blame] | 70 | |
Adrian Roos | 7bcf6d3 | 2017-04-04 16:44:25 -0700 | [diff] [blame] | 71 | protected NotificationTemplateViewWrapper(Context ctx, View view, |
| 72 | ExpandableNotificationRow row) { |
Selim Cinek | 7d1c63e | 2016-04-21 15:26:10 -0700 | [diff] [blame] | 73 | super(ctx, view, row); |
Selim Cinek | fd3e262 | 2016-01-12 16:02:42 -0800 | [diff] [blame] | 74 | mTransformationHelper.setCustomTransformation( |
| 75 | new ViewTransformationHelper.CustomTransformation() { |
| 76 | @Override |
| 77 | public boolean transformTo(TransformState ownState, |
Selim Cinek | 8f2f6a6 | 2016-02-23 19:56:31 -0800 | [diff] [blame] | 78 | TransformableView notification, final float transformationAmount) { |
Selim Cinek | fd3e262 | 2016-01-12 16:02:42 -0800 | [diff] [blame] | 79 | if (!(notification instanceof HybridNotificationView)) { |
| 80 | return false; |
| 81 | } |
| 82 | TransformState otherState = notification.getCurrentState( |
| 83 | TRANSFORMING_VIEW_TITLE); |
Selim Cinek | b66685b | 2016-02-02 17:16:08 -0800 | [diff] [blame] | 84 | final View text = ownState.getTransformedView(); |
Selim Cinek | 8f2f6a6 | 2016-02-23 19:56:31 -0800 | [diff] [blame] | 85 | CrossFadeHelper.fadeOut(text, transformationAmount); |
Selim Cinek | fd3e262 | 2016-01-12 16:02:42 -0800 | [diff] [blame] | 86 | if (otherState != null) { |
Selim Cinek | 8f2f6a6 | 2016-02-23 19:56:31 -0800 | [diff] [blame] | 87 | ownState.transformViewVerticalTo(otherState, this, |
| 88 | transformationAmount); |
Selim Cinek | fd3e262 | 2016-01-12 16:02:42 -0800 | [diff] [blame] | 89 | otherState.recycle(); |
| 90 | } |
| 91 | return true; |
| 92 | } |
| 93 | |
| 94 | @Override |
Selim Cinek | 8f2f6a6 | 2016-02-23 19:56:31 -0800 | [diff] [blame] | 95 | public boolean customTransformTarget(TransformState ownState, |
| 96 | TransformState otherState) { |
| 97 | float endY = getTransformationY(ownState, otherState); |
| 98 | ownState.setTransformationEndY(endY); |
| 99 | return true; |
| 100 | } |
| 101 | |
| 102 | @Override |
Selim Cinek | fd3e262 | 2016-01-12 16:02:42 -0800 | [diff] [blame] | 103 | public boolean transformFrom(TransformState ownState, |
Selim Cinek | 8f2f6a6 | 2016-02-23 19:56:31 -0800 | [diff] [blame] | 104 | TransformableView notification, float transformationAmount) { |
Selim Cinek | fd3e262 | 2016-01-12 16:02:42 -0800 | [diff] [blame] | 105 | if (!(notification instanceof HybridNotificationView)) { |
| 106 | return false; |
| 107 | } |
| 108 | TransformState otherState = notification.getCurrentState( |
| 109 | TRANSFORMING_VIEW_TITLE); |
Selim Cinek | b66685b | 2016-02-02 17:16:08 -0800 | [diff] [blame] | 110 | final View text = ownState.getTransformedView(); |
Selim Cinek | 8f2f6a6 | 2016-02-23 19:56:31 -0800 | [diff] [blame] | 111 | CrossFadeHelper.fadeIn(text, transformationAmount); |
Selim Cinek | fd3e262 | 2016-01-12 16:02:42 -0800 | [diff] [blame] | 112 | if (otherState != null) { |
Selim Cinek | 8f2f6a6 | 2016-02-23 19:56:31 -0800 | [diff] [blame] | 113 | ownState.transformViewVerticalFrom(otherState, this, |
| 114 | transformationAmount); |
Selim Cinek | fd3e262 | 2016-01-12 16:02:42 -0800 | [diff] [blame] | 115 | otherState.recycle(); |
| 116 | } |
| 117 | return true; |
| 118 | } |
Selim Cinek | 8f2f6a6 | 2016-02-23 19:56:31 -0800 | [diff] [blame] | 119 | |
| 120 | @Override |
| 121 | public boolean initTransformation(TransformState ownState, |
| 122 | TransformState otherState) { |
| 123 | float startY = getTransformationY(ownState, otherState); |
| 124 | ownState.setTransformationStartY(startY); |
| 125 | return true; |
| 126 | } |
| 127 | |
| 128 | private float getTransformationY(TransformState ownState, |
| 129 | TransformState otherState) { |
| 130 | int[] otherStablePosition = otherState.getLaidOutLocationOnScreen(); |
| 131 | int[] ownStablePosition = ownState.getLaidOutLocationOnScreen(); |
| 132 | return (otherStablePosition[1] |
| 133 | + otherState.getTransformedView().getHeight() |
| 134 | - ownStablePosition[1]) * 0.33f; |
| 135 | } |
| 136 | |
Selim Cinek | fd3e262 | 2016-01-12 16:02:42 -0800 | [diff] [blame] | 137 | }, TRANSFORMING_VIEW_TEXT); |
Selim Cinek | 4b259a1 | 2019-05-09 19:10:51 -0700 | [diff] [blame] | 138 | mTranslationForHeader = ctx.getResources().getDimensionPixelSize( |
| 139 | com.android.internal.R.dimen.notification_content_margin) |
| 140 | - ctx.getResources().getDimensionPixelSize( |
| 141 | com.android.internal.R.dimen.notification_content_margin_top); |
Jorim Jaggi | dacc924 | 2014-12-08 19:21:26 +0100 | [diff] [blame] | 142 | } |
| 143 | |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 144 | private void resolveTemplateViews(StatusBarNotification notification) { |
Selim Cinek | 65b2e7c | 2015-10-26 14:11:31 -0700 | [diff] [blame] | 145 | mPicture = (ImageView) mView.findViewById(com.android.internal.R.id.right_icon); |
Adrian Roos | 0aac04f | 2016-12-08 15:59:29 -0800 | [diff] [blame] | 146 | if (mPicture != null) { |
| 147 | mPicture.setTag(ImageTransformState.ICON_TAG, |
| 148 | notification.getNotification().getLargeIcon()); |
| 149 | } |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 150 | mTitle = (TextView) mView.findViewById(com.android.internal.R.id.title); |
| 151 | mText = (TextView) mView.findViewById(com.android.internal.R.id.text); |
Selim Cinek | 75fe38c | 2015-11-20 12:47:59 -0800 | [diff] [blame] | 152 | final View progress = mView.findViewById(com.android.internal.R.id.progress); |
| 153 | if (progress instanceof ProgressBar) { |
| 154 | mProgressBar = (ProgressBar) progress; |
| 155 | } else { |
| 156 | // It's still a viewstub |
| 157 | mProgressBar = null; |
| 158 | } |
Adrian Roos | 181385c | 2016-05-05 17:45:44 -0400 | [diff] [blame] | 159 | mActionsContainer = mView.findViewById(com.android.internal.R.id.actions_container); |
Selim Cinek | 396caca | 2018-04-10 17:46:46 -0700 | [diff] [blame] | 160 | mActions = mView.findViewById(com.android.internal.R.id.actions); |
Selim Cinek | 5d6ef8d | 2017-05-18 22:16:00 -0700 | [diff] [blame] | 161 | mReplyAction = mView.findViewById(com.android.internal.R.id.reply_icon_action); |
Selim Cinek | bee4e07 | 2018-05-21 22:06:43 -0700 | [diff] [blame] | 162 | mRemoteInputHistory = mView.findViewById( |
| 163 | com.android.internal.R.id.notification_material_reply_container); |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 164 | updatePendingIntentCancellations(); |
| 165 | } |
| 166 | |
| 167 | private void updatePendingIntentCancellations() { |
| 168 | if (mActions != null) { |
| 169 | int numActions = mActions.getChildCount(); |
| 170 | for (int i = 0; i < numActions; i++) { |
Selim Cinek | 019d71e | 2018-04-19 10:24:39 +0800 | [diff] [blame] | 171 | Button action = (Button) mActions.getChildAt(i); |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 172 | performOnPendingIntentCancellation(action, () -> { |
Selim Cinek | 019d71e | 2018-04-19 10:24:39 +0800 | [diff] [blame] | 173 | if (action.isEnabled()) { |
| 174 | action.setEnabled(false); |
| 175 | // The visual appearance doesn't look disabled enough yet, let's add the |
| 176 | // alpha as well. Since Alpha doesn't play nicely right now with the |
| 177 | // transformation, we rather blend it manually with the background color. |
| 178 | ColorStateList textColors = action.getTextColors(); |
| 179 | int[] colors = textColors.getColors(); |
| 180 | int[] newColors = new int[colors.length]; |
| 181 | float disabledAlpha = mView.getResources().getFloat( |
| 182 | com.android.internal.R.dimen.notification_action_disabled_alpha); |
| 183 | for (int j = 0; j < colors.length; j++) { |
| 184 | int color = colors[j]; |
| 185 | color = blendColorWithBackground(color, disabledAlpha); |
| 186 | newColors[j] = color; |
| 187 | } |
| 188 | ColorStateList newColorStateList = new ColorStateList( |
| 189 | textColors.getStates(), newColors); |
| 190 | action.setTextColor(newColorStateList); |
| 191 | } |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 192 | }); |
| 193 | } |
| 194 | } |
| 195 | if (mReplyAction != null) { |
Selim Cinek | 27732cc | 2018-05-29 17:01:05 -0700 | [diff] [blame] | 196 | // Let's reset the view on update, assuming the new pending intent isn't cancelled |
| 197 | // anymore. The color filter automatically resets when it's updated. |
| 198 | mReplyAction.setEnabled(true); |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 199 | performOnPendingIntentCancellation(mReplyAction, () -> { |
Selim Cinek | 019d71e | 2018-04-19 10:24:39 +0800 | [diff] [blame] | 200 | if (mReplyAction != null && mReplyAction.isEnabled()) { |
| 201 | mReplyAction.setEnabled(false); |
| 202 | // The visual appearance doesn't look disabled enough yet, let's add the |
| 203 | // alpha as well. Since Alpha doesn't play nicely right now with the |
| 204 | // transformation, we rather blend it manually with the background color. |
| 205 | Drawable drawable = mReplyAction.getDrawable().mutate(); |
| 206 | PorterDuffColorFilter colorFilter = |
| 207 | (PorterDuffColorFilter) drawable.getColorFilter(); |
| 208 | float disabledAlpha = mView.getResources().getFloat( |
| 209 | com.android.internal.R.dimen.notification_action_disabled_alpha); |
| 210 | if (colorFilter != null) { |
| 211 | int color = colorFilter.getColor(); |
| 212 | color = blendColorWithBackground(color, disabledAlpha); |
| 213 | drawable.mutate().setColorFilter(color, colorFilter.getMode()); |
| 214 | } else { |
| 215 | mReplyAction.setAlpha(disabledAlpha); |
| 216 | } |
| 217 | } |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 218 | }); |
| 219 | } |
| 220 | } |
| 221 | |
Selim Cinek | 019d71e | 2018-04-19 10:24:39 +0800 | [diff] [blame] | 222 | private int blendColorWithBackground(int color, float alpha) { |
| 223 | // alpha doesn't go well for color filters, so let's blend it manually |
Lucas Dupin | a291d19 | 2018-06-07 13:59:42 -0700 | [diff] [blame] | 224 | return ContrastColorUtil.compositeColors(Color.argb((int) (alpha * 255), |
Selim Cinek | 019d71e | 2018-04-19 10:24:39 +0800 | [diff] [blame] | 225 | Color.red(color), Color.green(color), Color.blue(color)), resolveBackgroundColor()); |
| 226 | } |
| 227 | |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 228 | private void performOnPendingIntentCancellation(View view, Runnable cancellationRunnable) { |
| 229 | PendingIntent pendingIntent = (PendingIntent) view.getTag( |
| 230 | com.android.internal.R.id.pending_intent_tag); |
| 231 | if (pendingIntent == null) { |
| 232 | return; |
| 233 | } |
| 234 | if (mCancelledPendingIntents.contains(pendingIntent)) { |
| 235 | cancellationRunnable.run(); |
| 236 | } else { |
| 237 | PendingIntent.CancelListener listener = (PendingIntent intent) -> { |
| 238 | mView.post(() -> { |
| 239 | mCancelledPendingIntents.add(pendingIntent); |
| 240 | cancellationRunnable.run(); |
| 241 | }); |
| 242 | }; |
| 243 | if (mUiOffloadThread == null) { |
| 244 | mUiOffloadThread = Dependency.get(UiOffloadThread.class); |
| 245 | } |
Selim Cinek | 75f30cd | 2018-05-04 13:13:09 -0700 | [diff] [blame] | 246 | if (view.isAttachedToWindow()) { |
| 247 | mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener)); |
| 248 | } |
Selim Cinek | d83203c | 2018-04-18 14:34:27 +0800 | [diff] [blame] | 249 | view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { |
| 250 | @Override |
| 251 | public void onViewAttachedToWindow(View v) { |
| 252 | mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener)); |
| 253 | } |
| 254 | |
| 255 | @Override |
| 256 | public void onViewDetachedFromWindow(View v) { |
| 257 | mUiOffloadThread.submit(() -> pendingIntent.unregisterCancelListener(listener)); |
| 258 | } |
| 259 | }); |
| 260 | } |
Selim Cinek | 5d6ef8d | 2017-05-18 22:16:00 -0700 | [diff] [blame] | 261 | } |
| 262 | |
| 263 | @Override |
| 264 | public boolean disallowSingleClick(float x, float y) { |
| 265 | if (mReplyAction != null && mReplyAction.getVisibility() == View.VISIBLE) { |
| 266 | if (isOnView(mReplyAction, x, y) || isOnView(mPicture, x, y)) { |
| 267 | return true; |
| 268 | } |
| 269 | } |
| 270 | return super.disallowSingleClick(x, y); |
| 271 | } |
| 272 | |
| 273 | private boolean isOnView(View view, float x, float y) { |
| 274 | View searchView = (View) view.getParent(); |
| 275 | while (searchView != null && !(searchView instanceof ExpandableNotificationRow)) { |
| 276 | searchView.getHitRect(mTmpRect); |
| 277 | x -= mTmpRect.left; |
| 278 | y -= mTmpRect.top; |
| 279 | searchView = (View) searchView.getParent(); |
| 280 | } |
| 281 | view.getHitRect(mTmpRect); |
| 282 | return mTmpRect.contains((int) x,(int) y); |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 283 | } |
| 284 | |
| 285 | @Override |
Selim Cinek | 131f1a4 | 2017-06-05 17:50:19 -0700 | [diff] [blame] | 286 | public void onContentUpdated(ExpandableNotificationRow row) { |
Selim Cinek | 646d205 | 2016-01-03 14:42:02 +0800 | [diff] [blame] | 287 | // Reinspect the notification. Before the super call, because the super call also updates |
| 288 | // the transformation types and we need to have our values set by then. |
Selim Cinek | a6ee4bd | 2017-09-20 22:52:29 +0000 | [diff] [blame] | 289 | resolveTemplateViews(row.getStatusBarNotification()); |
Selim Cinek | 131f1a4 | 2017-06-05 17:50:19 -0700 | [diff] [blame] | 290 | super.onContentUpdated(row); |
Selim Cinek | 4b259a1 | 2019-05-09 19:10:51 -0700 | [diff] [blame] | 291 | if (row.getHeaderVisibleAmount() != DEFAULT_HEADER_VISIBLE_AMOUNT) { |
| 292 | setHeaderVisibleAmount(row.getHeaderVisibleAmount()); |
| 293 | } |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 294 | } |
| 295 | |
| 296 | @Override |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 297 | protected void updateTransformedTypes() { |
| 298 | // This also clears the existing types |
| 299 | super.updateTransformedTypes(); |
| 300 | if (mTitle != null) { |
Adrian Roos | 7bcf6d3 | 2017-04-04 16:44:25 -0700 | [diff] [blame] | 301 | mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE, |
| 302 | mTitle); |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 303 | } |
| 304 | if (mText != null) { |
Adrian Roos | 7bcf6d3 | 2017-04-04 16:44:25 -0700 | [diff] [blame] | 305 | mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT, |
| 306 | mText); |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 307 | } |
| 308 | if (mPicture != null) { |
Adrian Roos | 7bcf6d3 | 2017-04-04 16:44:25 -0700 | [diff] [blame] | 309 | mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE, |
| 310 | mPicture); |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 311 | } |
| 312 | if (mProgressBar != null) { |
Adrian Roos | 7bcf6d3 | 2017-04-04 16:44:25 -0700 | [diff] [blame] | 313 | mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS, |
| 314 | mProgressBar); |
Selim Cinek | 4ffd636 | 2015-12-29 15:12:23 +0100 | [diff] [blame] | 315 | } |
Jorim Jaggi | dacc924 | 2014-12-08 19:21:26 +0100 | [diff] [blame] | 316 | } |
| 317 | |
| 318 | @Override |
Adrian Roos | 181385c | 2016-05-05 17:45:44 -0400 | [diff] [blame] | 319 | public void setContentHeight(int contentHeight, int minHeightHint) { |
| 320 | super.setContentHeight(contentHeight, minHeightHint); |
| 321 | |
| 322 | mContentHeight = contentHeight; |
| 323 | mMinHeightHint = minHeightHint; |
| 324 | updateActionOffset(); |
| 325 | } |
| 326 | |
Selim Cinek | 86bfcee | 2018-01-17 11:00:47 -0800 | [diff] [blame] | 327 | @Override |
| 328 | public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) { |
| 329 | if (super.shouldClipToRounding(topRounded, bottomRounded)) { |
| 330 | return true; |
| 331 | } |
| 332 | return bottomRounded && mActionsContainer != null |
| 333 | && mActionsContainer.getVisibility() != View.GONE; |
| 334 | } |
| 335 | |
Adrian Roos | 181385c | 2016-05-05 17:45:44 -0400 | [diff] [blame] | 336 | private void updateActionOffset() { |
| 337 | if (mActionsContainer != null) { |
| 338 | // We should never push the actions higher than they are in the headsup view. |
| 339 | int constrainedContentHeight = Math.max(mContentHeight, mMinHeightHint); |
Selim Cinek | aa9db1f | 2018-02-27 17:35:47 -0800 | [diff] [blame] | 340 | |
| 341 | // We also need to compensate for any header translation, since we're always at the end. |
| 342 | mActionsContainer.setTranslationY(constrainedContentHeight - mView.getHeight() |
| 343 | - getHeaderTranslation()); |
Adrian Roos | 181385c | 2016-05-05 17:45:44 -0400 | [diff] [blame] | 344 | } |
| 345 | } |
Selim Cinek | 396caca | 2018-04-10 17:46:46 -0700 | [diff] [blame] | 346 | |
| 347 | @Override |
Selim Cinek | 4b259a1 | 2019-05-09 19:10:51 -0700 | [diff] [blame] | 348 | public int getHeaderTranslation() { |
| 349 | return (int) mHeaderTranslation; |
| 350 | } |
| 351 | |
| 352 | @Override |
| 353 | public void setHeaderVisibleAmount(float headerVisibleAmount) { |
| 354 | super.setHeaderVisibleAmount(headerVisibleAmount); |
| 355 | mNotificationHeader.setAlpha(headerVisibleAmount); |
| 356 | mHeaderTranslation = (1.0f - headerVisibleAmount) * mTranslationForHeader; |
| 357 | mView.setTranslationY(mHeaderTranslation); |
| 358 | } |
| 359 | |
| 360 | @Override |
Selim Cinek | 396caca | 2018-04-10 17:46:46 -0700 | [diff] [blame] | 361 | public int getExtraMeasureHeight() { |
| 362 | int extra = 0; |
| 363 | if (mActions != null) { |
| 364 | extra = mActions.getExtraMeasureHeight(); |
| 365 | } |
Selim Cinek | bee4e07 | 2018-05-21 22:06:43 -0700 | [diff] [blame] | 366 | if (mRemoteInputHistory != null && mRemoteInputHistory.getVisibility() != View.GONE) { |
| 367 | extra += mRow.getContext().getResources().getDimensionPixelSize( |
| 368 | R.dimen.remote_input_history_extra_height); |
| 369 | } |
Selim Cinek | 396caca | 2018-04-10 17:46:46 -0700 | [diff] [blame] | 370 | return extra + super.getExtraMeasureHeight(); |
| 371 | } |
Jorim Jaggi | 4e857f4 | 2014-11-17 19:14:04 +0100 | [diff] [blame] | 372 | } |