ExpandableView.java revision 8efa6dde2b4f2cdbf046b87b7366404c3cc46219
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;
2424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinekimport android.widget.FrameLayout;
2524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinekimport com.android.systemui.R;
2624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek
2724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinekimport java.util.ArrayList;
28be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
29be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi/**
30be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi * An abstract view for expandable views.
31be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi */
3224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinekpublic abstract class ExpandableView extends FrameLayout {
3324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek
3424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    private final int mMaxNotificationHeight;
35be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
36be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    private OnHeightChangedListener mOnHeightChangedListener;
37be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    protected int mActualHeight;
38be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    protected int mClipTopAmount;
39be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    private boolean mActualHeightInitialized;
4024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    private ArrayList<View> mMatchParentViews = new ArrayList<View>();
41be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
42be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public ExpandableView(Context context, AttributeSet attrs) {
43be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        super(context, attrs);
4424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        mMaxNotificationHeight = getResources().getDimensionPixelSize(
4524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                R.dimen.notification_max_height);
46be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
47be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
48be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    @Override
4924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
5024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int ownMaxHeight = mMaxNotificationHeight;
5124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
5224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
5324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
5424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        if (hasFixedHeight || isHeightLimited) {
5524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            int size = MeasureSpec.getSize(heightMeasureSpec);
5624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            ownMaxHeight = Math.min(ownMaxHeight, size);
5724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        }
5824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST);
5924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int maxChildHeight = 0;
6024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int childCount = getChildCount();
6124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        for (int i = 0; i < childCount; i++) {
62c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek            View child = getChildAt(i);
6324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            int childHeightSpec = newHeightSpec;
6424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            ViewGroup.LayoutParams layoutParams = child.getLayoutParams();
6524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            if (layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT) {
6624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                if (layoutParams.height >= 0) {
6724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                    // An actual height is set
6824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                    childHeightSpec = layoutParams.height > ownMaxHeight
6924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                        ? MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.EXACTLY)
7024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                        : MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
7124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                }
7224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                child.measure(widthMeasureSpec, childHeightSpec);
7324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                int childHeight = child.getMeasuredHeight();
7424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                maxChildHeight = Math.max(maxChildHeight, childHeight);
7524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            } else {
7624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                mMatchParentViews.add(child);
7724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            }
7824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        }
7924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int ownHeight = hasFixedHeight ? ownMaxHeight : maxChildHeight;
8024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
8124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        for (View child : mMatchParentViews) {
8224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            child.measure(widthMeasureSpec, newHeightSpec);
83c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek        }
8424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        mMatchParentViews.clear();
8524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int width = MeasureSpec.getSize(widthMeasureSpec);
8624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        setMeasuredDimension(width, ownHeight);
8724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    }
8824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek
8924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    @Override
9024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
9124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        super.onLayout(changed, left, top, right, bottom);
92be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        if (!mActualHeightInitialized && mActualHeight == 0) {
933c3c3fc38c474924629aa591c98d6dc190ed4e83Jorim Jaggi            setActualHeight(getInitialHeight());
94be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        }
95be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
96be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
97c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    protected int getInitialHeight() {
98c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek        return getHeight();
99c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    }
100c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek
10100ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    @Override
10200ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    public boolean dispatchTouchEvent(MotionEvent ev) {
10300ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        if (filterMotionEvent(ev)) {
10400ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi            return super.dispatchTouchEvent(ev);
10500ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        }
10600ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        return false;
10700ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    }
10800ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi
10900ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    private boolean filterMotionEvent(MotionEvent event) {
11000ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        return event.getActionMasked() != MotionEvent.ACTION_DOWN
11100ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi                || event.getY() > mClipTopAmount && event.getY() < mActualHeight;
11200ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    }
11300ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi
114be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
115be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * Sets the actual height of this notification. This is different than the laid out
116be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding.
117d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     *
118d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param actualHeight The height of this notification.
119d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param notifyListeners Whether the listener should be informed about the change.
120be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
121d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    public void setActualHeight(int actualHeight, boolean notifyListeners) {
122be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        mActualHeight = actualHeight;
123d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi        if (notifyListeners) {
124d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi            notifyHeightChanged();
125d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi        }
126d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    }
127d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi
128d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    public void setActualHeight(int actualHeight) {
1293c3c3fc38c474924629aa591c98d6dc190ed4e83Jorim Jaggi        mActualHeightInitialized = true;
130d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi        setActualHeight(actualHeight, true);
131be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
132be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
133be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
134be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * See {@link #setActualHeight}.
135be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     *
1369cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi     * @return The current actual height of this notification.
137be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
138be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public int getActualHeight() {
139be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        return mActualHeight;
140be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
141be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
142be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
143be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * @return The maximum height of this notification.
144be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
1454222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    public int getMaxHeight() {
1464222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        return getHeight();
1474222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    }
1484222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi
1494222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    /**
1504222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi     * @return The minimum height of this notification.
1514222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi     */
1524222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    public int getMinHeight() {
1534222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        return getHeight();
1544222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    }
155be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
156be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
157d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * Sets the notification as dimmed. The default implementation does nothing.
158d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     *
159d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param dimmed Whether the notification should be dimmed.
160d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param fade Whether an animation should be played to change the state.
161d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     */
162d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    public void setDimmed(boolean dimmed, boolean fade) {
163d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    }
164d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi
165d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    /**
1669cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi     * @return The desired notification height.
1679cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi     */
1689cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    public int getIntrinsicHeight() {
169a5eaa6034dd48fab0f5a232c09ebed35f359963eSelim Cinek        return getHeight();
1709cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    }
1719cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi
1729cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    /**
173be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * Sets the amount this view should be clipped from the top. This is used when an expanded
174be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * notification is scrolling in the top or bottom stack.
175be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     *
176be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * @param clipTopAmount The amount of pixels this view should be clipped from top.
177be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
178be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public void setClipTopAmount(int clipTopAmount) {
179be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        mClipTopAmount = clipTopAmount;
180be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
181be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
182eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek    public int getClipTopAmount() {
183eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek        return mClipTopAmount;
184eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek    }
185eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek
186be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public void setOnHeightChangedListener(OnHeightChangedListener listener) {
187be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        mOnHeightChangedListener = listener;
188be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
189be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
190be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
1914222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi     * @return Whether we can expand this views content.
192be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
1934222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    public boolean isContentExpandable() {
1944222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        return false;
195be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
196be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
1979cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    public void notifyHeightChanged() {
1989cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi        if (mOnHeightChangedListener != null) {
1999cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi            mOnHeightChangedListener.onHeightChanged(this);
2009cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi        }
2019cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    }
2029cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi
203c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    public boolean isTransparent() {
204c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek        return false;
205c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    }
206c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek
207be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
2088efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     * Perform a remove animation on this view.
2098efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *
2108efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     * @param translationDirection The direction value from [-1 ... 1] indicating in which the
2118efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             animation should be performed. A value of -1 means that The
2128efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             remove animation should be performed upwards,
2138efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             such that the  child appears to be going away to the top. 1
2148efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             Should mean the opposite.
2158efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     * @param onFinishedRunnable A runnable which should be run when the animation is finished.
2168efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     */
2178efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek    public abstract void performRemoveAnimation(float translationDirection,
2188efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek            Runnable onFinishedRunnable);
2198efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek
2208efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek    public abstract void performAddAnimation(long delay);
2218efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek
2228efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek    /**
223be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * A listener notifying when {@link #getActualHeight} changes.
224be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
225be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public interface OnHeightChangedListener {
226be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        void onHeightChanged(ExpandableView view);
227be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
228be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi}
229