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 17 package com.android.systemui.statusbar.notification; 18 19 import android.content.Context; 20 import android.graphics.Color; 21 import android.graphics.drawable.ColorDrawable; 22 import android.graphics.drawable.Drawable; 23 import android.support.v4.graphics.ColorUtils; 24 import android.view.NotificationHeaderView; 25 import android.view.View; 26 27 import com.android.systemui.statusbar.CrossFadeHelper; 28 import com.android.systemui.statusbar.ExpandableNotificationRow; 29 import com.android.systemui.statusbar.TransformableView; 30 31 /** 32 * Wraps the actual notification content view; used to implement behaviors which are different for 33 * the individual templates and custom views. 34 */ 35 public abstract class NotificationViewWrapper implements TransformableView { 36 37 protected final View mView; 38 protected final ExpandableNotificationRow mRow; 39 private final NotificationDozeHelper mDozer; 40 41 protected boolean mDark; 42 private int mBackgroundColor = 0; 43 protected boolean mShouldInvertDark; 44 protected boolean mDarkInitialized = false; 45 wrap(Context ctx, View v, ExpandableNotificationRow row)46 public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) { 47 if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) { 48 if ("bigPicture".equals(v.getTag())) { 49 return new NotificationBigPictureTemplateViewWrapper(ctx, v, row); 50 } else if ("bigText".equals(v.getTag())) { 51 return new NotificationBigTextTemplateViewWrapper(ctx, v, row); 52 } else if ("media".equals(v.getTag()) || "bigMediaNarrow".equals(v.getTag())) { 53 return new NotificationMediaTemplateViewWrapper(ctx, v, row); 54 } else if ("messaging".equals(v.getTag())) { 55 return new NotificationMessagingTemplateViewWrapper(ctx, v, row); 56 } 57 return new NotificationTemplateViewWrapper(ctx, v, row); 58 } else if (v instanceof NotificationHeaderView) { 59 return new NotificationHeaderViewWrapper(ctx, v, row); 60 } else { 61 return new NotificationCustomViewWrapper(ctx, v, row); 62 } 63 } 64 NotificationViewWrapper(Context ctx, View view, ExpandableNotificationRow row)65 protected NotificationViewWrapper(Context ctx, View view, ExpandableNotificationRow row) { 66 mView = view; 67 mRow = row; 68 mDozer = createDozer(ctx); 69 onReinflated(); 70 } 71 createDozer(Context ctx)72 protected NotificationDozeHelper createDozer(Context ctx) { 73 return new NotificationDozeHelper(); 74 } 75 getDozer()76 protected NotificationDozeHelper getDozer() { 77 return mDozer; 78 } 79 80 /** 81 * In dark mode, we draw as little as possible, assuming a black background. 82 * 83 * @param dark whether we should display ourselves in dark mode 84 * @param fade whether to animate the transition if the mode changes 85 * @param delay if fading, the delay of the animation 86 */ setDark(boolean dark, boolean fade, long delay)87 public void setDark(boolean dark, boolean fade, long delay) { 88 mDark = dark; 89 mDarkInitialized = true; 90 } 91 92 /** 93 * Notifies this wrapper that the content of the view might have changed. 94 * @param row the row this wrapper is attached to 95 */ onContentUpdated(ExpandableNotificationRow row)96 public void onContentUpdated(ExpandableNotificationRow row) { 97 mDarkInitialized = false; 98 } 99 onReinflated()100 public void onReinflated() { 101 if (shouldClearBackgroundOnReapply()) { 102 mBackgroundColor = 0; 103 } 104 Drawable background = mView.getBackground(); 105 if (background instanceof ColorDrawable) { 106 mBackgroundColor = ((ColorDrawable) background).getColor(); 107 mView.setBackground(null); 108 } 109 mShouldInvertDark = mBackgroundColor == 0 || isColorLight(mBackgroundColor); 110 } 111 shouldClearBackgroundOnReapply()112 protected boolean shouldClearBackgroundOnReapply() { 113 return true; 114 } 115 isColorLight(int backgroundColor)116 private boolean isColorLight(int backgroundColor) { 117 return Color.alpha(backgroundColor) == 0 118 || ColorUtils.calculateLuminance(backgroundColor) > 0.5; 119 } 120 121 /** 122 * Update the appearance of the expand button. 123 * 124 * @param expandable should this view be expandable 125 * @param onClickListener the listener to invoke when the expand affordance is clicked on 126 */ updateExpandability(boolean expandable, View.OnClickListener onClickListener)127 public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {} 128 129 /** 130 * @return the notification header if it exists 131 */ getNotificationHeader()132 public NotificationHeaderView getNotificationHeader() { 133 return null; 134 } 135 136 @Override getCurrentState(int fadingView)137 public TransformState getCurrentState(int fadingView) { 138 return null; 139 } 140 141 @Override transformTo(TransformableView notification, Runnable endRunnable)142 public void transformTo(TransformableView notification, Runnable endRunnable) { 143 // By default we are fading out completely 144 CrossFadeHelper.fadeOut(mView, endRunnable); 145 } 146 147 @Override transformTo(TransformableView notification, float transformationAmount)148 public void transformTo(TransformableView notification, float transformationAmount) { 149 CrossFadeHelper.fadeOut(mView, transformationAmount); 150 } 151 152 @Override transformFrom(TransformableView notification)153 public void transformFrom(TransformableView notification) { 154 // By default we are fading in completely 155 CrossFadeHelper.fadeIn(mView); 156 } 157 158 @Override transformFrom(TransformableView notification, float transformationAmount)159 public void transformFrom(TransformableView notification, float transformationAmount) { 160 CrossFadeHelper.fadeIn(mView, transformationAmount); 161 } 162 163 @Override setVisible(boolean visible)164 public void setVisible(boolean visible) { 165 mView.animate().cancel(); 166 mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); 167 } 168 getCustomBackgroundColor()169 public int getCustomBackgroundColor() { 170 // Parent notifications should always use the normal background color 171 return mRow.isSummaryWithChildren() ? 0 : mBackgroundColor; 172 } 173 setLegacy(boolean legacy)174 public void setLegacy(boolean legacy) { 175 } 176 setContentHeight(int contentHeight, int minHeightHint)177 public void setContentHeight(int contentHeight, int minHeightHint) { 178 } 179 setRemoteInputVisible(boolean visible)180 public void setRemoteInputVisible(boolean visible) { 181 } 182 setIsChildInGroup(boolean isChildInGroup)183 public void setIsChildInGroup(boolean isChildInGroup) { 184 } 185 isDimmable()186 public boolean isDimmable() { 187 return true; 188 } 189 } 190