ExpandableNotificationRow.java revision dce3c4cca5d4df4cc49c1a9f0537e2fecdbc45d2
1/* 2 * Copyright (C) 2013 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 17package com.android.systemui.statusbar; 18 19import android.content.Context; 20import android.util.AttributeSet; 21import android.view.View; 22import android.view.accessibility.AccessibilityEvent; 23 24import com.android.systemui.R; 25 26public class ExpandableNotificationRow extends ActivatableNotificationView { 27 private int mRowMinHeight; 28 private int mRowMaxHeight; 29 30 /** Does this row contain layouts that can adapt to row expansion */ 31 private boolean mExpandable; 32 /** Has the user actively changed the expansion state of this row */ 33 private boolean mHasUserChangedExpansion; 34 /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */ 35 private boolean mUserExpanded; 36 /** Is the user touching this row */ 37 private boolean mUserLocked; 38 /** Are we showing the "public" version */ 39 private boolean mShowingPublic; 40 41 /** 42 * Is this notification expanded by the system. The expansion state can be overridden by the 43 * user expansion. 44 */ 45 private boolean mIsSystemExpanded; 46 47 /** 48 * Whether the notification expansion is disabled. This is the case on Keyguard. 49 */ 50 private boolean mExpansionDisabled; 51 52 private NotificationContentView mPublicLayout; 53 private NotificationContentView mPrivateLayout; 54 private int mMaxExpandHeight; 55 private NotificationActivator mActivator; 56 57 public ExpandableNotificationRow(Context context, AttributeSet attrs) { 58 super(context, attrs); 59 } 60 61 @Override 62 protected void onFinishInflate() { 63 super.onFinishInflate(); 64 mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic); 65 mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded); 66 67 mActivator = new NotificationActivator(this); 68 } 69 70 @Override 71 public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { 72 if (super.onRequestSendAccessibilityEvent(child, event)) { 73 // Add a record for the entire layout since its content is somehow small. 74 // The event comes from a leaf view that is interacted with. 75 AccessibilityEvent record = AccessibilityEvent.obtain(); 76 onInitializeAccessibilityEvent(record); 77 dispatchPopulateAccessibilityEvent(record); 78 event.appendRecord(record); 79 return true; 80 } 81 return false; 82 } 83 84 public void setHeightRange(int rowMinHeight, int rowMaxHeight) { 85 mRowMinHeight = rowMinHeight; 86 mRowMaxHeight = rowMaxHeight; 87 } 88 89 public boolean isExpandable() { 90 return mExpandable; 91 } 92 93 public void setExpandable(boolean expandable) { 94 mExpandable = expandable; 95 } 96 97 /** 98 * @return whether the user has changed the expansion state 99 */ 100 public boolean hasUserChangedExpansion() { 101 return mHasUserChangedExpansion; 102 } 103 104 public boolean isUserExpanded() { 105 return mUserExpanded; 106 } 107 108 /** 109 * Set this notification to be expanded by the user 110 * 111 * @param userExpanded whether the user wants this notification to be expanded 112 */ 113 public void setUserExpanded(boolean userExpanded) { 114 mHasUserChangedExpansion = true; 115 mUserExpanded = userExpanded; 116 } 117 118 public boolean isUserLocked() { 119 return mUserLocked; 120 } 121 122 public void setUserLocked(boolean userLocked) { 123 mUserLocked = userLocked; 124 } 125 126 /** 127 * @return has the system set this notification to be expanded 128 */ 129 public boolean isSystemExpanded() { 130 return mIsSystemExpanded; 131 } 132 133 /** 134 * Set this notification to be expanded by the system. 135 * 136 * @param expand whether the system wants this notification to be expanded. 137 */ 138 public void setSystemExpanded(boolean expand) { 139 mIsSystemExpanded = expand; 140 applyExpansionToLayout(); 141 } 142 143 /** 144 * @param expansionDisabled whether to prevent notification expansion 145 */ 146 public void setExpansionDisabled(boolean expansionDisabled) { 147 mExpansionDisabled = expansionDisabled; 148 applyExpansionToLayout(); 149 } 150 151 /** 152 * Apply an expansion state to the layout. 153 */ 154 public void applyExpansionToLayout() { 155 boolean expand = isExpanded(); 156 if (expand && mExpandable) { 157 setActualHeight(mMaxExpandHeight); 158 } else { 159 setActualHeight(mRowMinHeight); 160 } 161 } 162 163 /** 164 * If {@link #isExpanded()} then this is the greatest possible height this view can 165 * get and otherwise it is {@link #mRowMinHeight}. 166 * 167 * @return the maximum allowed expansion height of this view. 168 */ 169 public int getMaximumAllowedExpandHeight() { 170 if (isUserLocked()) { 171 return getActualHeight(); 172 } 173 boolean inExpansionState = isExpanded(); 174 if (!inExpansionState) { 175 // not expanded, so we return the collapsed size 176 return mRowMinHeight; 177 } 178 179 return mShowingPublic ? mRowMinHeight : getMaxExpandHeight(); 180 } 181 182 /** 183 * Check whether the view state is currently expanded. This is given by the system in {@link 184 * #setSystemExpanded(boolean)} and can be overridden by user expansion or 185 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this 186 * view can differ from this state, if layout params are modified from outside. 187 * 188 * @return whether the view state is currently expanded. 189 */ 190 private boolean isExpanded() { 191 return !mExpansionDisabled 192 && (!hasUserChangedExpansion() && isSystemExpanded() || isUserExpanded()); 193 } 194 195 @Override 196 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 197 super.onLayout(changed, left, top, right, bottom); 198 boolean updateExpandHeight = mMaxExpandHeight == 0; 199 mMaxExpandHeight = mPrivateLayout.getMaxHeight(); 200 if (updateExpandHeight) { 201 applyExpansionToLayout(); 202 } 203 } 204 205 public void setShowingPublic(boolean show) { 206 mShowingPublic = show; 207 208 // bail out if no public version 209 if (mPublicLayout.getChildCount() == 0) return; 210 211 // TODO: animation? 212 mPublicLayout.setVisibility(show ? View.VISIBLE : View.GONE); 213 mPrivateLayout.setVisibility(show ? View.GONE : View.VISIBLE); 214 } 215 216 /** 217 * Sets the notification as dimmed, meaning that it will appear in a more gray variant. 218 */ 219 public void setDimmed(boolean dimmed) { 220 super.setDimmed(dimmed); 221 mActivator.setDimmed(dimmed); 222 } 223 224 public int getMaxExpandHeight() { 225 return mMaxExpandHeight; 226 } 227 228 public NotificationActivator getActivator() { 229 return mActivator; 230 } 231 232 /** 233 * @return the potential height this view could expand in addition. 234 */ 235 public int getExpandPotential() { 236 return getMaximumAllowedExpandHeight() - getActualHeight(); 237 } 238 239 @Override 240 public void setActualHeight(int height) { 241 mPrivateLayout.setActualHeight(height); 242 invalidate(); 243 super.setActualHeight(height); 244 } 245 246 @Override 247 public int getMaxHeight() { 248 return mPrivateLayout.getMaxHeight(); 249 } 250 251 @Override 252 public void setClipTopAmount(int clipTopAmount) { 253 super.setClipTopAmount(clipTopAmount); 254 mPrivateLayout.setClipTopAmount(clipTopAmount); 255 } 256 257 public void notifyContentUpdated() { 258 mPrivateLayout.notifyContentUpdated(); 259 } 260} 261