ExpandableView.java revision c9c00ae2fa5fb787e9f12705f8cd8de445ecde4b
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; 20be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggiimport android.util.AttributeSet; 2100ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggiimport android.view.MotionEvent; 22be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggiimport android.view.View; 23c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinekimport android.view.ViewGroup; 24be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 25be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi/** 26be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * An abstract view for expandable views. 27be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 28c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinekpublic abstract class ExpandableView extends ViewGroup { 29be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 30be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi private OnHeightChangedListener mOnHeightChangedListener; 31be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi protected int mActualHeight; 32be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi protected int mClipTopAmount; 33be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi private boolean mActualHeightInitialized; 34be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 35be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public ExpandableView(Context context, AttributeSet attrs) { 36be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi super(context, attrs); 37be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 38be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 39be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi @Override 40be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 41c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek for (int i = 0; i < getChildCount(); i++) { 42c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek View child = getChildAt(i); 43c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek int height = child.getMeasuredHeight(); 44c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek int width = child.getMeasuredWidth(); 45c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek int center = getWidth() / 2; 46c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek int childLeft = center - width / 2; 47c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek child.layout(childLeft, 48c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek 0, 49c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek childLeft + width, 50c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek height); 51c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek } 52be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi if (!mActualHeightInitialized && mActualHeight == 0) { 53c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek mActualHeight = getInitialHeight(); 54be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 55be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi mActualHeightInitialized = true; 56be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 57be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 58c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek protected int getInitialHeight() { 59c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek return getHeight(); 60c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek } 61c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek 6200ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi @Override 6300ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi public boolean dispatchTouchEvent(MotionEvent ev) { 6400ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi if (filterMotionEvent(ev)) { 6500ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi return super.dispatchTouchEvent(ev); 6600ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi } 6700ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi return false; 6800ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi } 6900ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi 7000ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi private boolean filterMotionEvent(MotionEvent event) { 7100ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi return event.getActionMasked() != MotionEvent.ACTION_DOWN 7200ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi || event.getY() > mClipTopAmount && event.getY() < mActualHeight; 7300ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi } 7400ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi 75be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 76be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * Sets the actual height of this notification. This is different than the laid out 77be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding. 78d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * 79d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * @param actualHeight The height of this notification. 80d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * @param notifyListeners Whether the listener should be informed about the change. 81be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 82d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi public void setActualHeight(int actualHeight, boolean notifyListeners) { 83be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi mActualHeight = actualHeight; 84d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi if (notifyListeners) { 85d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi notifyHeightChanged(); 86d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi } 87d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi } 88d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi 89d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi public void setActualHeight(int actualHeight) { 90d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi setActualHeight(actualHeight, true); 91be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 92be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 93be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 94be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * See {@link #setActualHeight}. 95be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * 969cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi * @return The current actual height of this notification. 97be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 98be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public int getActualHeight() { 99be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi return mActualHeight; 100be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 101be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 102be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 103be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * @return The maximum height of this notification. 104be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 1054222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi public int getMaxHeight() { 1064222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi return getHeight(); 1074222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi } 1084222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi 1094222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi /** 1104222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi * @return The minimum height of this notification. 1114222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi */ 1124222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi public int getMinHeight() { 1134222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi return getHeight(); 1144222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi } 115be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 116be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 117d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * Sets the notification as dimmed. The default implementation does nothing. 118d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * 119d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * @param dimmed Whether the notification should be dimmed. 120d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi * @param fade Whether an animation should be played to change the state. 121d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi */ 122d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi public void setDimmed(boolean dimmed, boolean fade) { 123d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi } 124d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi 125d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi /** 1269cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi * @return The desired notification height. 1279cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi */ 1289cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi public int getIntrinsicHeight() { 129a5eaa6034dd48fab0f5a232c09ebed35f359963eSelim Cinek return getHeight(); 1309cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi } 1319cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi 1329cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi /** 133be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * Sets the amount this view should be clipped from the top. This is used when an expanded 134be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * notification is scrolling in the top or bottom stack. 135be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * 136be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * @param clipTopAmount The amount of pixels this view should be clipped from top. 137be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 138be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public void setClipTopAmount(int clipTopAmount) { 139be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi mClipTopAmount = clipTopAmount; 140be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 141be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 142eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek public int getClipTopAmount() { 143eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek return mClipTopAmount; 144eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek } 145eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek 146be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public void setOnHeightChangedListener(OnHeightChangedListener listener) { 147be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi mOnHeightChangedListener = listener; 148be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 149be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 150be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 1514222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi * @return Whether we can expand this views content. 152be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 1534222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi public boolean isContentExpandable() { 1544222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi return false; 155be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 156be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi 1579cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi public void notifyHeightChanged() { 1589cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi if (mOnHeightChangedListener != null) { 1599cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi mOnHeightChangedListener.onHeightChanged(this); 1609cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi } 1619cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi } 1629cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi 163c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek public boolean isTransparent() { 164c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek return false; 165c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek } 166c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek 167be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi /** 168be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * A listener notifying when {@link #getActualHeight} changes. 169be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */ 170be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi public interface OnHeightChangedListener { 171be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi void onHeightChanged(ExpandableView view); 172be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi } 173be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi} 174