ExpandableNotificationRow.java revision 863834bd96bdebcf21f4c4a7d8285d4858c061e4
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 boolean mIsBelowSpeedBump; 56 private View mVetoButton; 57 58 public ExpandableNotificationRow(Context context, AttributeSet attrs) { 59 super(context, attrs); 60 } 61 62 @Override 63 protected void onFinishInflate() { 64 super.onFinishInflate(); 65 mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic); 66 mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded); 67 mVetoButton = findViewById(R.id.veto); 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 notifyHeightChanged(); 141 } 142 143 /** 144 * @param expansionDisabled whether to prevent notification expansion 145 */ 146 public void setExpansionDisabled(boolean expansionDisabled) { 147 mExpansionDisabled = expansionDisabled; 148 notifyHeightChanged(); 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 @Override 164 public int getIntrinsicHeight() { 165 if (isUserLocked()) { 166 return getActualHeight(); 167 } 168 boolean inExpansionState = isExpanded(); 169 if (!inExpansionState) { 170 // not expanded, so we return the collapsed size 171 return mRowMinHeight; 172 } 173 174 return mShowingPublic ? mRowMinHeight : getMaxExpandHeight(); 175 } 176 177 /** 178 * Check whether the view state is currently expanded. This is given by the system in {@link 179 * #setSystemExpanded(boolean)} and can be overridden by user expansion or 180 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this 181 * view can differ from this state, if layout params are modified from outside. 182 * 183 * @return whether the view state is currently expanded. 184 */ 185 private boolean isExpanded() { 186 return !mExpansionDisabled 187 && (!hasUserChangedExpansion() && isSystemExpanded() || isUserExpanded()); 188 } 189 190 @Override 191 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 192 super.onLayout(changed, left, top, right, bottom); 193 boolean updateExpandHeight = mMaxExpandHeight == 0; 194 mMaxExpandHeight = mPrivateLayout.getMaxHeight(); 195 if (updateExpandHeight) { 196 applyExpansionToLayout(); 197 } 198 } 199 200 public void setShowingPublic(boolean show) { 201 mShowingPublic = show; 202 203 // bail out if no public version 204 if (mPublicLayout.getChildCount() == 0) return; 205 206 // TODO: animation? 207 mPublicLayout.setVisibility(show ? View.VISIBLE : View.GONE); 208 mPrivateLayout.setVisibility(show ? View.GONE : View.VISIBLE); 209 } 210 211 public int getMaxExpandHeight() { 212 return mMaxExpandHeight; 213 } 214 215 /** 216 * @return the potential height this view could expand in addition. 217 */ 218 public int getExpandPotential() { 219 return getIntrinsicHeight() - getActualHeight(); 220 } 221 222 @Override 223 public boolean isContentExpandable() { 224 return mPrivateLayout.isContentExpandable(); 225 } 226 227 @Override 228 public void setActualHeight(int height, boolean notifyListeners) { 229 mPrivateLayout.setActualHeight(height); 230 invalidate(); 231 super.setActualHeight(height, notifyListeners); 232 } 233 234 @Override 235 public int getMaxHeight() { 236 return mPrivateLayout.getMaxHeight(); 237 } 238 239 @Override 240 public int getMinHeight() { 241 return mPrivateLayout.getMinHeight(); 242 } 243 244 @Override 245 public void setClipTopAmount(int clipTopAmount) { 246 super.setClipTopAmount(clipTopAmount); 247 mPrivateLayout.setClipTopAmount(clipTopAmount); 248 } 249 250 public boolean isBelowSpeedBump() { 251 return mIsBelowSpeedBump; 252 } 253 254 public void setIsBelowSpeedBump(boolean isBelow) { 255 this.mIsBelowSpeedBump = isBelow; 256 } 257 258 public void notifyContentUpdated() { 259 mPrivateLayout.notifyContentUpdated(); 260 } 261 262 @Override 263 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 264 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 265 int newHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY); 266 mVetoButton.measure(widthMeasureSpec, newHeightSpec); 267 } 268} 269