ExpandableView.java revision d552d9d8e964c102e6832610be46cf2c041e8829
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar;
18
19import android.content.Context;
20import android.util.AttributeSet;
21import android.view.MotionEvent;
22import android.view.View;
23import android.widget.FrameLayout;
24
25/**
26 * An abstract view for expandable views.
27 */
28public abstract class ExpandableView extends FrameLayout {
29
30    private OnHeightChangedListener mOnHeightChangedListener;
31    protected int mActualHeight;
32    protected int mClipTopAmount;
33    private boolean mActualHeightInitialized;
34
35    public ExpandableView(Context context, AttributeSet attrs) {
36        super(context, attrs);
37    }
38
39    @Override
40    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
41        super.onLayout(changed, left, top, right, bottom);
42        if (!mActualHeightInitialized && mActualHeight == 0) {
43            mActualHeight = getHeight();
44        }
45        mActualHeightInitialized = true;
46    }
47
48    @Override
49    public boolean dispatchTouchEvent(MotionEvent ev) {
50        if (filterMotionEvent(ev)) {
51            return super.dispatchTouchEvent(ev);
52        }
53        return false;
54    }
55
56    private boolean filterMotionEvent(MotionEvent event) {
57        return event.getActionMasked() != MotionEvent.ACTION_DOWN
58                || event.getY() > mClipTopAmount && event.getY() < mActualHeight;
59    }
60
61    /**
62     * Sets the actual height of this notification. This is different than the laid out
63     * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding.
64     *
65     * @param actualHeight The height of this notification.
66     * @param notifyListeners Whether the listener should be informed about the change.
67     */
68    public void setActualHeight(int actualHeight, boolean notifyListeners) {
69        mActualHeight = actualHeight;
70        if (notifyListeners) {
71            notifyHeightChanged();
72        }
73    }
74
75    public void setActualHeight(int actualHeight) {
76        setActualHeight(actualHeight, true);
77    }
78
79    /**
80     * See {@link #setActualHeight}.
81     *
82     * @return The current actual height of this notification.
83     */
84    public int getActualHeight() {
85        return mActualHeight;
86    }
87
88    /**
89     * @return The maximum height of this notification.
90     */
91    public int getMaxHeight() {
92        return getHeight();
93    }
94
95    /**
96     * @return The minimum height of this notification.
97     */
98    public int getMinHeight() {
99        return getHeight();
100    }
101
102    /**
103     * Sets the notification as dimmed. The default implementation does nothing.
104     *
105     * @param dimmed Whether the notification should be dimmed.
106     * @param fade Whether an animation should be played to change the state.
107     */
108    public void setDimmed(boolean dimmed, boolean fade) {
109    }
110
111    /**
112     * @return The desired notification height.
113     */
114    public int getIntrinsicHeight() {
115        return mActualHeight;
116    }
117
118    /**
119     * Sets the amount this view should be clipped from the top. This is used when an expanded
120     * notification is scrolling in the top or bottom stack.
121     *
122     * @param clipTopAmount The amount of pixels this view should be clipped from top.
123     */
124    public void setClipTopAmount(int clipTopAmount) {
125        mClipTopAmount = clipTopAmount;
126    }
127
128    public int getClipTopAmount() {
129        return mClipTopAmount;
130    }
131
132    public void setOnHeightChangedListener(OnHeightChangedListener listener) {
133        mOnHeightChangedListener = listener;
134    }
135
136    /**
137     * @return Whether we can expand this views content.
138     */
139    public boolean isContentExpandable() {
140        return false;
141    }
142
143    public void notifyHeightChanged() {
144        if (mOnHeightChangedListener != null) {
145            mOnHeightChangedListener.onHeightChanged(this);
146        }
147    }
148
149    /**
150     * A listener notifying when {@link #getActualHeight} changes.
151     */
152    public interface OnHeightChangedListener {
153        void onHeightChanged(ExpandableView view);
154    }
155}
156