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;
424e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi    private boolean mDark;
4324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    private ArrayList<View> mMatchParentViews = new ArrayList<View>();
44be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
45be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public ExpandableView(Context context, AttributeSet attrs) {
46be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        super(context, attrs);
4724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        mMaxNotificationHeight = getResources().getDimensionPixelSize(
4824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                R.dimen.notification_max_height);
49be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
50be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
51be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    @Override
5224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
5324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int ownMaxHeight = mMaxNotificationHeight;
5424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
5524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
5624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
5724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        if (hasFixedHeight || isHeightLimited) {
5824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            int size = MeasureSpec.getSize(heightMeasureSpec);
5924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            ownMaxHeight = Math.min(ownMaxHeight, size);
6024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        }
6124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST);
6224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int maxChildHeight = 0;
6324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int childCount = getChildCount();
6424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        for (int i = 0; i < childCount; i++) {
65c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek            View child = getChildAt(i);
6624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            int childHeightSpec = newHeightSpec;
6724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            ViewGroup.LayoutParams layoutParams = child.getLayoutParams();
6824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            if (layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT) {
6924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                if (layoutParams.height >= 0) {
7024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                    // An actual height is set
7124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                    childHeightSpec = layoutParams.height > ownMaxHeight
7224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                        ? MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.EXACTLY)
7324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                        : MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
7424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                }
75b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi                child.measure(
76b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi                        getChildMeasureSpec(widthMeasureSpec, 0 /* padding */, layoutParams.width),
77b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi                        childHeightSpec);
7824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                int childHeight = child.getMeasuredHeight();
7924d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                maxChildHeight = Math.max(maxChildHeight, childHeight);
8024d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            } else {
8124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek                mMatchParentViews.add(child);
8224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek            }
8324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        }
8424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int ownHeight = hasFixedHeight ? ownMaxHeight : maxChildHeight;
8524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
8624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        for (View child : mMatchParentViews) {
87b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi            child.measure(getChildMeasureSpec(
88b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi                    widthMeasureSpec, 0 /* padding */, child.getLayoutParams().width),
89b741f053394b6e8f59bdf72bb47e9f4484fbb808Jorim Jaggi                    newHeightSpec);
90c9c00ae2fa5fb787e9f12705f8cd8de445ecde4bSelim Cinek        }
9124d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        mMatchParentViews.clear();
9224d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        int width = MeasureSpec.getSize(widthMeasureSpec);
9324d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        setMeasuredDimension(width, ownHeight);
9424d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    }
9524d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek
9624d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    @Override
9724d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
9824d7cfa4d6a3331708bb7b37f551b4f534b02f7cSelim Cinek        super.onLayout(changed, left, top, right, bottom);
99be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        if (!mActualHeightInitialized && mActualHeight == 0) {
100d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek            int initialHeight = getInitialHeight();
101d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek            if (initialHeight != 0) {
102d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek                setActualHeight(initialHeight);
103d2319fbe6a53ac4c38ca02e4d8e32da86ed0994bSelim Cinek            }
104be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        }
105be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
106be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
1071a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek    /**
1081a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek     * Resets the height of the view on the next layout pass
1091a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek     */
1101a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek    protected void resetActualHeight() {
111310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren        mActualHeight = 0;
112310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren        mActualHeightInitialized = false;
1131a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek        requestLayout();
114310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren    }
115310df3127aace5a82cdc107fdb1e2d6957f38bccChris Wren
116c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    protected int getInitialHeight() {
117c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek        return getHeight();
118c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    }
119c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek
12000ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    @Override
12100ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    public boolean dispatchTouchEvent(MotionEvent ev) {
12200ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        if (filterMotionEvent(ev)) {
12300ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi            return super.dispatchTouchEvent(ev);
12400ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        }
12500ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        return false;
12600ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    }
12700ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi
1281a521f3ea841f6db9686bbec7f950a3883d075aaSelim Cinek    protected boolean filterMotionEvent(MotionEvent event) {
12900ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi        return event.getActionMasked() != MotionEvent.ACTION_DOWN
13000ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi                || event.getY() > mClipTopAmount && event.getY() < mActualHeight;
13100ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi    }
13200ebdfe8ba98c05a767660de2ed7c9a19fb49d74Jorim Jaggi
133be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
134be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * Sets the actual height of this notification. This is different than the laid out
135be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding.
136d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     *
137d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param actualHeight The height of this notification.
138d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param notifyListeners Whether the listener should be informed about the change.
139be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
140d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    public void setActualHeight(int actualHeight, boolean notifyListeners) {
1412580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi        mActualHeightInitialized = true;
142be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        mActualHeight = actualHeight;
143d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi        if (notifyListeners) {
144d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi            notifyHeightChanged();
145d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi        }
146d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    }
147d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi
148d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    public void setActualHeight(int actualHeight) {
149d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi        setActualHeight(actualHeight, true);
150be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
151be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
152be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
153be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * See {@link #setActualHeight}.
154be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     *
1559cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi     * @return The current actual height of this notification.
156be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
157be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public int getActualHeight() {
158be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        return mActualHeight;
159be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
160be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
161be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
162be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * @return The maximum height of this notification.
163be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
1644222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    public int getMaxHeight() {
1654222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        return getHeight();
1664222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    }
1674222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi
1684222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    /**
1694222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi     * @return The minimum height of this notification.
1704222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi     */
1714222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    public int getMinHeight() {
1724222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        return getHeight();
1734222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    }
174be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
175be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
176d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * Sets the notification as dimmed. The default implementation does nothing.
177d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     *
178d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param dimmed Whether the notification should be dimmed.
179d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     * @param fade Whether an animation should be played to change the state.
180d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi     */
181d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    public void setDimmed(boolean dimmed, boolean fade) {
182d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    }
183d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi
184d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi    /**
185bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock     * Sets the notification as dark. The default implementation does nothing.
186bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock     *
187bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock     * @param dark Whether the notification should be dark.
188bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock     * @param fade Whether an animation should be played to change the state.
1894e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi     * @param delay If fading, the delay of the animation.
190bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock     */
1914e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi    public void setDark(boolean dark, boolean fade, long delay) {
1924e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi        mDark = dark;
1934e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi    }
1944e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi
1954e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi    public boolean isDark() {
1964e857f4ef0357e05806819d0488a73a12208fe8fJorim Jaggi        return mDark;
197bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock    }
198bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock
199bf370992508c55d1f2493923bdc1834a0710e4baJohn Spurlock    /**
200ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * See {@link #setHideSensitive}. This is a variant which notifies this view in advance about
201ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * the upcoming state of hiding sensitive notifications. It gets called at the very beginning
202ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * of a stack scroller update such that the updated intrinsic height (which is dependent on
203ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * whether private or public layout is showing) gets taken into account into all layout
204ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * calculations.
205ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     */
206ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
207ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    }
208ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi
209ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    /**
210ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     * Sets whether the notification should hide its private contents if it is sensitive.
211ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi     */
212ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
213ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi            long duration) {
214ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    }
215ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi
216ae44128776410abd11bd06ae700db9cc4606a773Jorim Jaggi    /**
2179cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi     * @return The desired notification height.
2189cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi     */
2199cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    public int getIntrinsicHeight() {
220a5eaa6034dd48fab0f5a232c09ebed35f359963eSelim Cinek        return getHeight();
2219cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    }
2229cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi
2239cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    /**
224be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * Sets the amount this view should be clipped from the top. This is used when an expanded
225be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * notification is scrolling in the top or bottom stack.
226be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     *
227be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * @param clipTopAmount The amount of pixels this view should be clipped from top.
228be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
229be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public void setClipTopAmount(int clipTopAmount) {
230be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        mClipTopAmount = clipTopAmount;
231be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
232be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
233eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek    public int getClipTopAmount() {
234eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek        return mClipTopAmount;
235eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek    }
236eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek
237be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public void setOnHeightChangedListener(OnHeightChangedListener listener) {
238be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        mOnHeightChangedListener = listener;
239be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
240be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
241be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
2424222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi     * @return Whether we can expand this views content.
243be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
2444222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi    public boolean isContentExpandable() {
2454222d9a7fb87d73e1443ec1a2de9782b05741af6Jorim Jaggi        return false;
246be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
247be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi
2489cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    public void notifyHeightChanged() {
2499cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi        if (mOnHeightChangedListener != null) {
2509cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi            mOnHeightChangedListener.onHeightChanged(this);
2519cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi        }
2529cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi    }
2539cbadd3c08a7d7dd3412743dd04aecb16c5a1595Jorim Jaggi
254c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    public boolean isTransparent() {
255c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek        return false;
256c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek    }
257c27437b7fd04e682ae2abdf0727a99bf5c6e409dSelim Cinek
258be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    /**
2598efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     * Perform a remove animation on this view.
2608efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *
26160d07c597c3f996deb3f2743466fe5279ca15e8dJorim Jaggi     * @param duration The duration of the remove animation.
2628efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     * @param translationDirection The direction value from [-1 ... 1] indicating in which the
2638efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             animation should be performed. A value of -1 means that The
2648efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             remove animation should be performed upwards,
2658efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             such that the  child appears to be going away to the top. 1
2668efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     *                             Should mean the opposite.
2678efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     * @param onFinishedRunnable A runnable which should be run when the animation is finished.
2688efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek     */
26960d07c597c3f996deb3f2743466fe5279ca15e8dJorim Jaggi    public abstract void performRemoveAnimation(long duration, float translationDirection,
2708efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek            Runnable onFinishedRunnable);
2718efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek
27260d07c597c3f996deb3f2743466fe5279ca15e8dJorim Jaggi    public abstract void performAddAnimation(long delay, long duration);
2738efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek
2743d2b94bf8e32640e57573ebb17911b1db9440231Selim Cinek    public void setBelowSpeedBump(boolean below) {
2753d2b94bf8e32640e57573ebb17911b1db9440231Selim Cinek    }
2763d2b94bf8e32640e57573ebb17911b1db9440231Selim Cinek
27731094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek    public void onHeightReset() {
278e34c6513bb1a4d3e246866c2a7f0619914f18bd3Selim Cinek        if (mOnHeightChangedListener != null) {
279e34c6513bb1a4d3e246866c2a7f0619914f18bd3Selim Cinek            mOnHeightChangedListener.onReset(this);
280e34c6513bb1a4d3e246866c2a7f0619914f18bd3Selim Cinek        }
281a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek    }
282a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek
2838efa6dde2b4f2cdbf046b87b7366404c3cc46219Selim Cinek    /**
284e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * This method returns the drawing rect for the view which is different from the regular
285e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at
286e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * position 0 and usually the translation is neglected. Since we are manually clipping this
287e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * view,we also need to subtract the clipTopAmount from the top. This is needed in order to
288e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * ensure that accessibility and focusing work correctly.
289e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     *
290e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     * @param outRect The (scrolled) drawing bounds of the view.
291e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek     */
292e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek    @Override
293e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek    public void getDrawingRect(Rect outRect) {
294e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek        super.getDrawingRect(outRect);
295e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek        outRect.left += getTranslationX();
296e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek        outRect.right += getTranslationX();
297e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek        outRect.bottom = (int) (outRect.top + getTranslationY() + getActualHeight());
298e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek        outRect.top += getTranslationY() + getClipTopAmount();
299e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek    }
300e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek
301e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek    /**
302be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     * A listener notifying when {@link #getActualHeight} changes.
303be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi     */
304be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    public interface OnHeightChangedListener {
30530c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi
30630c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi        /**
30730c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi         * @param view the view for which the height changed, or {@code null} if just the top
30830c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi         *             padding or the padding between the elements changed
30930c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi         */
310be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi        void onHeightChanged(ExpandableView view);
311a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek
312a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek        /**
313a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek         * Called when the view is reset and therefore the height will change abruptly
314a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek         *
315a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek         * @param view The view which was reset.
316a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek         */
317a5e211b1f2a8d055b369dadc464dc5d5bc3dd9c1Selim Cinek        void onReset(ExpandableView view);
318be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi    }
319be565dfc1c17b7ddafa9753851b8f82849fd3f42Jorim Jaggi}
320