ExpandableNotificationRow.java revision 11298830114a195a149ef23633c96fb3cef5399b
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 mShowingPublic ? mRowMinHeight : mMaxExpandHeight; 213 } 214 215 @Override 216 public boolean isContentExpandable() { 217 NotificationContentView showingLayout = getShowingLayout(); 218 return showingLayout.isContentExpandable(); 219 } 220 221 @Override 222 public void setActualHeight(int height, boolean notifyListeners) { 223 mPrivateLayout.setActualHeight(height); 224 mPublicLayout.setActualHeight(height); 225 invalidate(); 226 super.setActualHeight(height, notifyListeners); 227 } 228 229 @Override 230 public int getMaxHeight() { 231 NotificationContentView showingLayout = getShowingLayout(); 232 return showingLayout.getMaxHeight(); 233 } 234 235 @Override 236 public int getMinHeight() { 237 NotificationContentView showingLayout = getShowingLayout(); 238 return showingLayout.getMinHeight(); 239 } 240 241 @Override 242 public void setClipTopAmount(int clipTopAmount) { 243 super.setClipTopAmount(clipTopAmount); 244 mPrivateLayout.setClipTopAmount(clipTopAmount); 245 mPublicLayout.setClipTopAmount(clipTopAmount); 246 } 247 248 public boolean isBelowSpeedBump() { 249 return mIsBelowSpeedBump; 250 } 251 252 public void setIsBelowSpeedBump(boolean isBelow) { 253 this.mIsBelowSpeedBump = isBelow; 254 } 255 256 public void notifyContentUpdated() { 257 mPublicLayout.notifyContentUpdated(); 258 mPrivateLayout.notifyContentUpdated(); 259 } 260 261 public boolean isShowingLayoutLayouted() { 262 NotificationContentView showingLayout = getShowingLayout(); 263 return showingLayout.getWidth() != 0; 264 } 265 266 private NotificationContentView getShowingLayout() { 267 return mShowingPublic ? mPublicLayout : mPrivateLayout; 268 } 269} 270