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
36b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    private final int mBottomDecorHeight;
37b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    protected OnHeightChangedListener mOnHeightChangedListener;
38379ff8f6b18b236b679a59a2dc14c0baeede3baeSelim Cinek    protected int mMaxViewHeight;
39310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren    private int mActualHeight;
40be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    protected int mClipTopAmount;
41be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    private boolean mActualHeightInitialized;
424e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi    private boolean mDark;
4324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    private ArrayList<View> mMatchParentViews = new ArrayList<View>();
44a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek    private int mClipTopOptimization;
45a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek    private static Rect mClipRect = new Rect();
462cd45dfba6a9105a305ea20b110ba5ac078a9dc6Selim Cinek    private boolean mWillBeGone;
479c17b7749377a047794157bc066e45d985cabf52Selim Cinek    private int mMinClipTopAmount = 0;
48be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
49be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public ExpandableView(Context context, AttributeSet attrs) {
50be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        super(context, attrs);
51379ff8f6b18b236b679a59a2dc14c0baeede3baeSelim Cinek        mMaxViewHeight = getResources().getDimensionPixelSize(
5224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                R.dimen.notification_max_height);
53b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        mBottomDecorHeight = resolveBottomDecorHeight();
54b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    }
55b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek
56b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    protected int resolveBottomDecorHeight() {
57b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        return getResources().getDimensionPixelSize(
58b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek                R.dimen.notification_bottom_decor_height);
59be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
60be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
61be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    @Override
6224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
63379ff8f6b18b236b679a59a2dc14c0baeede3baeSelim Cinek        int ownMaxHeight = mMaxViewHeight;
646f145cf0c02fdbd324ff2d62a86f19bff5eb7ebeSelim Cinek        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
656f145cf0c02fdbd324ff2d62a86f19bff5eb7ebeSelim Cinek        boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
666f145cf0c02fdbd324ff2d62a86f19bff5eb7ebeSelim Cinek        if (hasFixedHeight) {
676f145cf0c02fdbd324ff2d62a86f19bff5eb7ebeSelim Cinek            // We have a height set in our layout, so we want to be at most as big as given
686f145cf0c02fdbd324ff2d62a86f19bff5eb7ebeSelim Cinek            ownMaxHeight = Math.min(MeasureSpec.getSize(heightMeasureSpec), ownMaxHeight);
696f145cf0c02fdbd324ff2d62a86f19bff5eb7ebeSelim Cinek        }
7024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST);
7124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int maxChildHeight = 0;
7224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int childCount = getChildCount();
7324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        for (int i = 0; i < childCount; i++) {
74c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek            View child = getChildAt(i);
75b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek            if (child.getVisibility() == GONE || isChildInvisible(child)) {
76b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek                continue;
77b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek            }
7824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            int childHeightSpec = newHeightSpec;
7924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            ViewGroup.LayoutParams layoutParams = child.getLayoutParams();
8024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            if (layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT) {
8124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                if (layoutParams.height >= 0) {
8224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                    // An actual height is set
8324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                    childHeightSpec = layoutParams.height > ownMaxHeight
8424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                        ? MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.EXACTLY)
8524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                        : MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
8624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                }
87b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi                child.measure(
88b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi                        getChildMeasureSpec(widthMeasureSpec, 0 /* padding */, layoutParams.width),
89b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi                        childHeightSpec);
9024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                int childHeight = child.getMeasuredHeight();
9124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                maxChildHeight = Math.max(maxChildHeight, childHeight);
9224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            } else {
9324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                mMatchParentViews.add(child);
9424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            }
9524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        }
966f145cf0c02fdbd324ff2d62a86f19bff5eb7ebeSelim Cinek        int ownHeight = hasFixedHeight ? ownMaxHeight : Math.min(ownMaxHeight, maxChildHeight);
9724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
9824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        for (View child : mMatchParentViews) {
99b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi            child.measure(getChildMeasureSpec(
100b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi                    widthMeasureSpec, 0 /* padding */, child.getLayoutParams().width),
101b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi                    newHeightSpec);
102c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek        }
10324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        mMatchParentViews.clear();
10424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int width = MeasureSpec.getSize(widthMeasureSpec);
105b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        if (canHaveBottomDecor()) {
106b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek            // We always account for the expandAction as well.
107b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek            ownHeight += mBottomDecorHeight;
108b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        }
10924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        setMeasuredDimension(width, ownHeight);
11024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    }
11124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek
11224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    @Override
11324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
11424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        super.onLayout(changed, left, top, right, bottom);
115be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        if (!mActualHeightInitialized && mActualHeight == 0) {
116d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek            int initialHeight = getInitialHeight();
117d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek            if (initialHeight != 0) {
118b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek                setContentHeight(initialHeight);
119d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek            }
120be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        }
121ba67acff25950a32476273b5d60192a3874c2130Selim Cinek        updateClipping();
122be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
123be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
1241a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek    /**
1251a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek     * Resets the height of the view on the next layout pass
1261a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek     */
1271a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek    protected void resetActualHeight() {
128310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren        mActualHeight = 0;
129310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren        mActualHeightInitialized = false;
1301a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek        requestLayout();
131310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren    }
132310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren
133c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    protected int getInitialHeight() {
134c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek        return getHeight();
135c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    }
136c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek
13700ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    @Override
138e0c1890bdc5482a4d29aba683115a7133ab58950Adrian Roos    public boolean dispatchGenericMotionEvent(MotionEvent ev) {
139e0c1890bdc5482a4d29aba683115a7133ab58950Adrian Roos        if (filterMotionEvent(ev)) {
140e0c1890bdc5482a4d29aba683115a7133ab58950Adrian Roos            return super.dispatchGenericMotionEvent(ev);
141e0c1890bdc5482a4d29aba683115a7133ab58950Adrian Roos        }
142e0c1890bdc5482a4d29aba683115a7133ab58950Adrian Roos        return false;
143e0c1890bdc5482a4d29aba683115a7133ab58950Adrian Roos    }
144e0c1890bdc5482a4d29aba683115a7133ab58950Adrian Roos
145e0c1890bdc5482a4d29aba683115a7133ab58950Adrian Roos    @Override
14600ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    public boolean dispatchTouchEvent(MotionEvent ev) {
14700ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        if (filterMotionEvent(ev)) {
14800ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi            return super.dispatchTouchEvent(ev);
14900ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        }
15000ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        return false;
15100ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    }
15200ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi
1531a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek    protected boolean filterMotionEvent(MotionEvent event) {
15400ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        return event.getActionMasked() != MotionEvent.ACTION_DOWN
155e0c1890bdc5482a4d29aba683115a7133ab58950Adrian Roos                && event.getActionMasked() != MotionEvent.ACTION_HOVER_ENTER
156e0c1890bdc5482a4d29aba683115a7133ab58950Adrian Roos                && event.getActionMasked() != MotionEvent.ACTION_HOVER_MOVE
15700ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi                || event.getY() > mClipTopAmount && event.getY() < mActualHeight;
15800ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    }
15900ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi
160be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
161be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * Sets the actual height of this notification. This is different than the laid out
162be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding.
163d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     *
164d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param actualHeight The height of this notification.
165d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param notifyListeners Whether the listener should be informed about the change.
166be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
167d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    public void setActualHeight(int actualHeight, boolean notifyListeners) {
1682580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi        mActualHeightInitialized = true;
169be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        mActualHeight = actualHeight;
170a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek        updateClipping();
171d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi        if (notifyListeners) {
172b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek            notifyHeightChanged(false  /* needsAnimation */);
173d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi        }
174d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    }
175d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi
176b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    public void setContentHeight(int contentHeight) {
177b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        setActualHeight(contentHeight + getBottomDecorHeight(), true);
178be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
179be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
180be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
181be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * See {@link #setActualHeight}.
182be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     *
1839cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi     * @return The current actual height of this notification.
184be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
185be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public int getActualHeight() {
186be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        return mActualHeight;
187be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
188be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
189be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
190b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     * This view may have a bottom decor which will be placed below the content. If it has one, this
191b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     * view will be layouted higher than just the content by {@link #mBottomDecorHeight}.
192b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     * @return the height of the decor if it currently has one
193b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     */
194b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    public int getBottomDecorHeight() {
195b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        return hasBottomDecor() ? mBottomDecorHeight : 0;
196b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    }
197b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek
198b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    /**
199b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     * @return whether this view may have a bottom decor at all. This will force the view to layout
200b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     *         itself higher than just it's content
201b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     */
202b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    protected boolean canHaveBottomDecor() {
203b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        return false;
204b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    }
205b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek
206b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    /**
207b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     * @return whether this view has a decor view below it's content. This will make the intrinsic
208b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     *         height from {@link #getIntrinsicHeight()} higher as well
209b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     */
210b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    protected boolean hasBottomDecor() {
211b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        return false;
212b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    }
213b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek
214b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    /**
215be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * @return The maximum height of this notification.
216be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
217b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    public int getMaxContentHeight() {
2184222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        return getHeight();
2194222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    }
2204222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi
2214222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    /**
222b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     * @return The minimum content height of this notification.
2234222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi     */
2244222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    public int getMinHeight() {
2254222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        return getHeight();
2264222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    }
227be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
228be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
229d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * Sets the notification as dimmed. The default implementation does nothing.
230d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     *
231d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param dimmed Whether the notification should be dimmed.
232d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param fade Whether an animation should be played to change the state.
233d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     */
234d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    public void setDimmed(boolean dimmed, boolean fade) {
235d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    }
236d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi
237d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    /**
238bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock     * Sets the notification as dark. The default implementation does nothing.
239bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock     *
240bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock     * @param dark Whether the notification should be dark.
241bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock     * @param fade Whether an animation should be played to change the state.
2424e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi     * @param delay If fading, the delay of the animation.
243bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock     */
2444e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi    public void setDark(boolean dark, boolean fade, long delay) {
2454e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi        mDark = dark;
2464e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi    }
2474e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi
2484e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi    public boolean isDark() {
2494e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi        return mDark;
250bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock    }
251bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock
252bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock    /**
253ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * See {@link #setHideSensitive}. This is a variant which notifies this view in advance about
254ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * the upcoming state of hiding sensitive notifications. It gets called at the very beginning
255ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * of a stack scroller update such that the updated intrinsic height (which is dependent on
256ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * whether private or public layout is showing) gets taken into account into all layout
257ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * calculations.
258ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     */
259ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
260ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    }
261ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi
262ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    /**
263ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * Sets whether the notification should hide its private contents if it is sensitive.
264ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     */
265ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
266ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi            long duration) {
267ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    }
268ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi
269ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    /**
2709cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi     * @return The desired notification height.
2719cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi     */
2729cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    public int getIntrinsicHeight() {
273a5eaa6034dd48fab0f5a232c09ebed35f359963eSelim Cinek        return getHeight();
2749cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    }
2759cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi
2769cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    /**
277be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * Sets the amount this view should be clipped from the top. This is used when an expanded
278be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * notification is scrolling in the top or bottom stack.
279be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     *
280be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * @param clipTopAmount The amount of pixels this view should be clipped from top.
281be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
282be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public void setClipTopAmount(int clipTopAmount) {
283be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        mClipTopAmount = clipTopAmount;
284be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
285be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
286eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek    public int getClipTopAmount() {
287eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek        return mClipTopAmount;
288eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek    }
289eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek
290be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public void setOnHeightChangedListener(OnHeightChangedListener listener) {
291be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        mOnHeightChangedListener = listener;
292be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
293be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
294be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
2954222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi     * @return Whether we can expand this views content.
296be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
2974222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    public boolean isContentExpandable() {
2984222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        return false;
299be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
300be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
301b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    public void notifyHeightChanged(boolean needsAnimation) {
3029cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi        if (mOnHeightChangedListener != null) {
303b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek            mOnHeightChangedListener.onHeightChanged(this, needsAnimation);
3049cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi        }
3059cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    }
3069cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi
307c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    public boolean isTransparent() {
308c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek        return false;
309c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    }
310c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek
311be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
3128efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     * Perform a remove animation on this view.
3138efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *
31460d07c597c3f996deb3f2743466fe5279ca15e8dJorim Jaggi     * @param duration The duration of the remove animation.
3158efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     * @param translationDirection The direction value from [-1 ... 1] indicating in which the
3168efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             animation should be performed. A value of -1 means that The
3178efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             remove animation should be performed upwards,
3188efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             such that the  child appears to be going away to the top. 1
3198efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             Should mean the opposite.
3208efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     * @param onFinishedRunnable A runnable which should be run when the animation is finished.
3218efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     */
32260d07c597c3f996deb3f2743466fe5279ca15e8dJorim Jaggi    public abstract void performRemoveAnimation(long duration, float translationDirection,
3238efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek            Runnable onFinishedRunnable);
3248efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek
32560d07c597c3f996deb3f2743466fe5279ca15e8dJorim Jaggi    public abstract void performAddAnimation(long delay, long duration);
3268efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek
3273d2b94bf8e32640e57573ebb17911b1db9440231Selim Cinek    public void setBelowSpeedBump(boolean below) {
3283d2b94bf8e32640e57573ebb17911b1db9440231Selim Cinek    }
3293d2b94bf8e32640e57573ebb17911b1db9440231Selim Cinek
33031094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek    public void onHeightReset() {
331e34c6513bb1a4d3e246866c2a7f0619914f18bd3Selim Cinek        if (mOnHeightChangedListener != null) {
332e34c6513bb1a4d3e246866c2a7f0619914f18bd3Selim Cinek            mOnHeightChangedListener.onReset(this);
333e34c6513bb1a4d3e246866c2a7f0619914f18bd3Selim Cinek        }
334a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek    }
335a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek
3368efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek    /**
337e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * This method returns the drawing rect for the view which is different from the regular
338e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at
339e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * position 0 and usually the translation is neglected. Since we are manually clipping this
340e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * view,we also need to subtract the clipTopAmount from the top. This is needed in order to
341e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * ensure that accessibility and focusing work correctly.
342e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     *
343e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * @param outRect The (scrolled) drawing bounds of the view.
344e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     */
345e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek    @Override
346e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek    public void getDrawingRect(Rect outRect) {
347e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek        super.getDrawingRect(outRect);
348e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek        outRect.left += getTranslationX();
349e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek        outRect.right += getTranslationX();
350e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek        outRect.bottom = (int) (outRect.top + getTranslationY() + getActualHeight());
351e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek        outRect.top += getTranslationY() + getClipTopAmount();
352e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek    }
353e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek
354cd55f43db60c2f641252d829bd3f532358625834Adrian Roos    @Override
355cd55f43db60c2f641252d829bd3f532358625834Adrian Roos    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
356cd55f43db60c2f641252d829bd3f532358625834Adrian Roos        super.getBoundsOnScreen(outRect, clipToParent);
357b44f5486ef7c2e169d5a65eb159a1d842d9c3d51Adrian Roos        outRect.bottom = outRect.top + getActualHeight();
358b44f5486ef7c2e169d5a65eb159a1d842d9c3d51Adrian Roos        outRect.top += getClipTopOptimization();
359cd55f43db60c2f641252d829bd3f532358625834Adrian Roos    }
360cd55f43db60c2f641252d829bd3f532358625834Adrian Roos
361b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    public int getContentHeight() {
362b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        return mActualHeight - getBottomDecorHeight();
363b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    }
364b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek
365b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    /**
366b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     * @return whether the given child can be ignored for layouting and measuring purposes
367b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek     */
368b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    protected boolean isChildInvisible(View child) {
369b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        return false;
370b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    }
371b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek
372b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    public boolean areChildrenExpanded() {
373b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        return false;
374b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek    }
375b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek
376a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek    private void updateClipping() {
377f92a1fdb77311149189ae17244adc51017b89c1eSelim Cinek        int top = mClipTopOptimization;
378f92a1fdb77311149189ae17244adc51017b89c1eSelim Cinek        if (top >= getActualHeight()) {
379f92a1fdb77311149189ae17244adc51017b89c1eSelim Cinek            top = getActualHeight() - 1;
380f92a1fdb77311149189ae17244adc51017b89c1eSelim Cinek        }
381f92a1fdb77311149189ae17244adc51017b89c1eSelim Cinek        mClipRect.set(0, top, getWidth(), getActualHeight());
382a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek        setClipBounds(mClipRect);
383a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek    }
384a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek
385a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek    public int getClipTopOptimization() {
386a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek        return mClipTopOptimization;
387a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek    }
388a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek
389a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek    /**
390a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek     * Set that the view will be clipped by a given amount from the top. Contrary to
391a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek     * {@link #setClipTopAmount} this amount doesn't effect shadows and the background.
392a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek     *
393a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek     * @param clipTopOptimization the amount to clip from the top
394a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek     */
395a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek    public void setClipTopOptimization(int clipTopOptimization) {
396a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek        mClipTopOptimization = clipTopOptimization;
397a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek        updateClipping();
398a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek    }
399a272dfed9a4f31d8245099c0d99a73e79b90670cSelim Cinek
4002cd45dfba6a9105a305ea20b110ba5ac078a9dc6Selim Cinek    public boolean willBeGone() {
4012cd45dfba6a9105a305ea20b110ba5ac078a9dc6Selim Cinek        return mWillBeGone;
4022cd45dfba6a9105a305ea20b110ba5ac078a9dc6Selim Cinek    }
4032cd45dfba6a9105a305ea20b110ba5ac078a9dc6Selim Cinek
4042cd45dfba6a9105a305ea20b110ba5ac078a9dc6Selim Cinek    public void setWillBeGone(boolean willBeGone) {
4052cd45dfba6a9105a305ea20b110ba5ac078a9dc6Selim Cinek        mWillBeGone = willBeGone;
4062cd45dfba6a9105a305ea20b110ba5ac078a9dc6Selim Cinek    }
4072cd45dfba6a9105a305ea20b110ba5ac078a9dc6Selim Cinek
4089c17b7749377a047794157bc066e45d985cabf52Selim Cinek    public int getMinClipTopAmount() {
4099c17b7749377a047794157bc066e45d985cabf52Selim Cinek        return mMinClipTopAmount;
4109c17b7749377a047794157bc066e45d985cabf52Selim Cinek    }
4119c17b7749377a047794157bc066e45d985cabf52Selim Cinek
4129c17b7749377a047794157bc066e45d985cabf52Selim Cinek    public void setMinClipTopAmount(int minClipTopAmount) {
4139c17b7749377a047794157bc066e45d985cabf52Selim Cinek        mMinClipTopAmount = minClipTopAmount;
4149c17b7749377a047794157bc066e45d985cabf52Selim Cinek    }
4159c17b7749377a047794157bc066e45d985cabf52Selim Cinek
416e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek    /**
417be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * A listener notifying when {@link #getActualHeight} changes.
418be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
419be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public interface OnHeightChangedListener {
42030c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi
42130c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi        /**
42230c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi         * @param view the view for which the height changed, or {@code null} if just the top
42330c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi         *             padding or the padding between the elements changed
424b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek         * @param needsAnimation whether the view height needs to be animated
42530c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi         */
426b5605e58cb8080c8c887b1885336b707596c8094Selim Cinek        void onHeightChanged(ExpandableView view, boolean needsAnimation);
427a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek
428a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek        /**
429a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek         * Called when the view is reset and therefore the height will change abruptly
430a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek         *
431a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek         * @param view The view which was reset.
432a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek         */
433a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek        void onReset(ExpandableView view);
434be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
435be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi}
436