ExpandableView.java revision 310df3127aace5a82cdc107fdb1e2d6957f38bcc
1be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi/* 2be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * Copyright (C) 2014 The Android Open Source Project 3be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * 4be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 5be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * you may not use this file except in compliance with the License. 6be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * You may obtain a copy of the License at 7be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * 8be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 9be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * 10be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * Unless required by applicable law or agreed to in writing, software 11be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 12be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * See the License for the specific language governing permissions and 14be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * limitations under the License 15be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 16be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 17be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggipackage com.android.systemui.statusbar; 18be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 19be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggiimport android.content.Context; 20e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinekimport android.graphics.Rect; 21be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggiimport android.util.AttributeSet; 2200ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggiimport android.view.MotionEvent; 23be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggiimport android.view.View; 24c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinekimport android.view.ViewGroup; 2524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinekimport android.widget.FrameLayout; 2624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinekimport com.android.systemui.R; 27e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinekimport com.android.systemui.statusbar.stack.NotificationStackScrollLayout; 2824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek 2924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinekimport java.util.ArrayList; 30be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 31be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi/** 32be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * An abstract view for expandable views. 33be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 3424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinekpublic abstract class ExpandableView extends FrameLayout { 3524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek 3624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek private final int mMaxNotificationHeight; 37be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 38be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi private OnHeightChangedListener mOnHeightChangedListener; 39310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren private int mActualHeight; 40be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi protected int mClipTopAmount; 41be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi private boolean mActualHeightInitialized; 4224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek private ArrayList<View> mMatchParentViews = new ArrayList<View>(); 43be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 44be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public ExpandableView(Context context, AttributeSet attrs) { 45be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi super(context, attrs); 4624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek mMaxNotificationHeight = getResources().getDimensionPixelSize( 4724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek R.dimen.notification_max_height); 48be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 49be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 50be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi @Override 5124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 5224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek int ownMaxHeight = mMaxNotificationHeight; 5324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek int heightMode = MeasureSpec.getMode(heightMeasureSpec); 5424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY; 5524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST; 5624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek if (hasFixedHeight || isHeightLimited) { 5724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek int size = MeasureSpec.getSize(heightMeasureSpec); 5824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek ownMaxHeight = Math.min(ownMaxHeight, size); 5924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek } 6024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST); 6124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek int maxChildHeight = 0; 6224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek int childCount = getChildCount(); 6324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek for (int i = 0; i < childCount; i++) { 64c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek View child = getChildAt(i); 6524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek int childHeightSpec = newHeightSpec; 6624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek ViewGroup.LayoutParams layoutParams = child.getLayoutParams(); 6724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek if (layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT) { 6824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek if (layoutParams.height >= 0) { 6924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek // An actual height is set 7024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek childHeightSpec = layoutParams.height > ownMaxHeight 7124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek ? MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.EXACTLY) 7224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek : MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY); 7324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek } 74b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi child.measure( 75b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi getChildMeasureSpec(widthMeasureSpec, 0 /* padding */, layoutParams.width), 76b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi childHeightSpec); 7724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek int childHeight = child.getMeasuredHeight(); 7824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek maxChildHeight = Math.max(maxChildHeight, childHeight); 7924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek } else { 8024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek mMatchParentViews.add(child); 8124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek } 8224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek } 8324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek int ownHeight = hasFixedHeight ? ownMaxHeight : maxChildHeight; 8424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY); 8524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek for (View child : mMatchParentViews) { 86b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi child.measure(getChildMeasureSpec( 87b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi widthMeasureSpec, 0 /* padding */, child.getLayoutParams().width), 88b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi newHeightSpec); 89c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek } 9024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek mMatchParentViews.clear(); 9124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek int width = MeasureSpec.getSize(widthMeasureSpec); 9224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek setMeasuredDimension(width, ownHeight); 9324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek } 9424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek 9524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek @Override 9624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 9724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek super.onLayout(changed, left, top, right, bottom); 98be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi if (!mActualHeightInitialized && mActualHeight == 0) { 99d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek int initialHeight = getInitialHeight(); 100d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek if (initialHeight != 0) { 101d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek setActualHeight(initialHeight); 102d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek } 103be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 104be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 105be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 106310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren protected void resetHeight() { 107310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren mActualHeight = 0; 108310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren mActualHeightInitialized = false; 109310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren } 110310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren 111c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek protected int getInitialHeight() { 112c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek return getHeight(); 113c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek } 114c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek 11500ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi @Override 11600ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi public boolean dispatchTouchEvent(MotionEvent ev) { 11700ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi if (filterMotionEvent(ev)) { 11800ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi return super.dispatchTouchEvent(ev); 11900ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi } 12000ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi return false; 12100ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi } 12200ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi 12300ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi private boolean filterMotionEvent(MotionEvent event) { 12400ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi return event.getActionMasked() != MotionEvent.ACTION_DOWN 12500ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi || event.getY() > mClipTopAmount && event.getY() < mActualHeight; 12600ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi } 12700ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi 128be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 129be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * Sets the actual height of this notification. This is different than the laid out 130be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding. 131d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * 132d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * @param actualHeight The height of this notification. 133d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * @param notifyListeners Whether the listener should be informed about the change. 134be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 135d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi public void setActualHeight(int actualHeight, boolean notifyListeners) { 1362580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi mActualHeightInitialized = true; 137be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi mActualHeight = actualHeight; 138d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi if (notifyListeners) { 139d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi notifyHeightChanged(); 140d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi } 141d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi } 142d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi 143d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi public void setActualHeight(int actualHeight) { 144d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi setActualHeight(actualHeight, true); 145be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 146be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 147be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 148be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * See {@link #setActualHeight}. 149be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * 1509cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi * @return The current actual height of this notification. 151be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 152be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public int getActualHeight() { 153be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi return mActualHeight; 154be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 155be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 156be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 157be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * @return The maximum height of this notification. 158be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 1594222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi public int getMaxHeight() { 1604222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi return getHeight(); 1614222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi } 1624222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi 1634222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi /** 1644222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi * @return The minimum height of this notification. 1654222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi */ 1664222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi public int getMinHeight() { 1674222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi return getHeight(); 1684222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi } 169be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 170be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 171d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * Sets the notification as dimmed. The default implementation does nothing. 172d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * 173d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * @param dimmed Whether the notification should be dimmed. 174d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * @param fade Whether an animation should be played to change the state. 175d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi */ 176d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi public void setDimmed(boolean dimmed, boolean fade) { 177d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi } 178d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi 179d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi /** 180bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock * Sets the notification as dark. The default implementation does nothing. 181bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock * 182bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock * @param dark Whether the notification should be dark. 183bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock * @param fade Whether an animation should be played to change the state. 184bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock */ 185bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock public void setDark(boolean dark, boolean fade) { 186bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock } 187bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock 188bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock /** 189ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi * See {@link #setHideSensitive}. This is a variant which notifies this view in advance about 190ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi * the upcoming state of hiding sensitive notifications. It gets called at the very beginning 191ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi * of a stack scroller update such that the updated intrinsic height (which is dependent on 192ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi * whether private or public layout is showing) gets taken into account into all layout 193ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi * calculations. 194ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi */ 195ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) { 196ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi } 197ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi 198ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi /** 199ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi * Sets whether the notification should hide its private contents if it is sensitive. 200ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi */ 201ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi public void setHideSensitive(boolean hideSensitive, boolean animated, long delay, 202ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi long duration) { 203ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi } 204ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi 205ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi /** 2069cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi * @return The desired notification height. 2079cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi */ 2089cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi public int getIntrinsicHeight() { 209a5eaa6034dd48fab0f5a232c09ebed35f359963eSelim Cinek return getHeight(); 2109cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi } 2119cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi 2129cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi /** 213be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * Sets the amount this view should be clipped from the top. This is used when an expanded 214be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * notification is scrolling in the top or bottom stack. 215be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * 216be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * @param clipTopAmount The amount of pixels this view should be clipped from top. 217be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 218be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public void setClipTopAmount(int clipTopAmount) { 219be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi mClipTopAmount = clipTopAmount; 220be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 221be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 222eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek public int getClipTopAmount() { 223eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek return mClipTopAmount; 224eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek } 225eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek 226be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public void setOnHeightChangedListener(OnHeightChangedListener listener) { 227be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi mOnHeightChangedListener = listener; 228be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 229be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 230be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 2314222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi * @return Whether we can expand this views content. 232be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 2334222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi public boolean isContentExpandable() { 2344222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi return false; 235be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 236be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 2379cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi public void notifyHeightChanged() { 2389cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi if (mOnHeightChangedListener != null) { 2399cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi mOnHeightChangedListener.onHeightChanged(this); 2409cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi } 2419cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi } 2429cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi 243c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek public boolean isTransparent() { 244c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek return false; 245c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek } 246c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek 247be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 2488efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek * Perform a remove animation on this view. 2498efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek * 25060d07c597c3f996deb3f2743466fe5279ca15e8dJorim Jaggi * @param duration The duration of the remove animation. 2518efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek * @param translationDirection The direction value from [-1 ... 1] indicating in which the 2528efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek * animation should be performed. A value of -1 means that The 2538efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek * remove animation should be performed upwards, 2548efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek * such that the child appears to be going away to the top. 1 2558efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek * Should mean the opposite. 2568efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek * @param onFinishedRunnable A runnable which should be run when the animation is finished. 2578efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek */ 25860d07c597c3f996deb3f2743466fe5279ca15e8dJorim Jaggi public abstract void performRemoveAnimation(long duration, float translationDirection, 2598efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek Runnable onFinishedRunnable); 2608efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek 26160d07c597c3f996deb3f2743466fe5279ca15e8dJorim Jaggi public abstract void performAddAnimation(long delay, long duration); 2628efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek 2633d2b94bf8e32640e57573ebb17911b1db9440231Selim Cinek public void setBelowSpeedBump(boolean below) { 2643d2b94bf8e32640e57573ebb17911b1db9440231Selim Cinek } 2653d2b94bf8e32640e57573ebb17911b1db9440231Selim Cinek 26631094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek public void onHeightReset() { 267e34c6513bb1a4d3e246866c2a7f0619914f18bd3Selim Cinek if (mOnHeightChangedListener != null) { 268e34c6513bb1a4d3e246866c2a7f0619914f18bd3Selim Cinek mOnHeightChangedListener.onReset(this); 269e34c6513bb1a4d3e246866c2a7f0619914f18bd3Selim Cinek } 270a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek } 271a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek 2728efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek /** 273e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek * This method returns the drawing rect for the view which is different from the regular 274e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at 275e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek * position 0 and usually the translation is neglected. Since we are manually clipping this 276e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek * view,we also need to subtract the clipTopAmount from the top. This is needed in order to 277e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek * ensure that accessibility and focusing work correctly. 278e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek * 279e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek * @param outRect The (scrolled) drawing bounds of the view. 280e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek */ 281e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek @Override 282e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek public void getDrawingRect(Rect outRect) { 283e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek super.getDrawingRect(outRect); 284e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek outRect.left += getTranslationX(); 285e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek outRect.right += getTranslationX(); 286e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek outRect.bottom = (int) (outRect.top + getTranslationY() + getActualHeight()); 287e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek outRect.top += getTranslationY() + getClipTopAmount(); 288e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek } 289e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek 290e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek /** 291be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * A listener notifying when {@link #getActualHeight} changes. 292be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 293be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public interface OnHeightChangedListener { 29430c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi 29530c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi /** 29630c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi * @param view the view for which the height changed, or {@code null} if just the top 29730c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi * padding or the padding between the elements changed 29830c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi */ 299be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi void onHeightChanged(ExpandableView view); 300a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek 301a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek /** 302a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek * Called when the view is reset and therefore the height will change abruptly 303a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek * 304a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek * @param view The view which was reset. 305a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek */ 306a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek void onReset(ExpandableView view); 307be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 308be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi} 309