ExpandableView.java revision c27437b7fd04e682ae2abdf0727a99bf5c6e409d
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 = getInitialHeight();
44        }
45        mActualHeightInitialized = true;
46    }
47
48    protected int getInitialHeight() {
49        return getHeight();
50    }
51
52    @Override
53    public boolean dispatchTouchEvent(MotionEvent ev) {
54        if (filterMotionEvent(ev)) {
55            return super.dispatchTouchEvent(ev);
56        }
57        return false;
58    }
59
60    private boolean filterMotionEvent(MotionEvent event) {
61        return event.getActionMasked() != MotionEvent.ACTION_DOWN
62                || event.getY() > mClipTopAmount && event.getY() < mActualHeight;
63    }
64
65    /**
66     * Sets the actual height of this notification. This is different than the laid out
67     * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding.
68     *
69     * @param actualHeight The height of this notification.
70     * @param notifyListeners Whether the listener should be informed about the change.
71     */
72    public void setActualHeight(int actualHeight, boolean notifyListeners) {
73        mActualHeight = actualHeight;
74        if (notifyListeners) {
75            notifyHeightChanged();
76        }
77    }
78
79    public void setActualHeight(int actualHeight) {
80        setActualHeight(actualHeight, true);
81    }
82
83    /**
84     * See {@link #setActualHeight}.
85     *
86     * @return The current actual height of this notification.
87     */
88    public int getActualHeight() {
89        return mActualHeight;
90    }
91
92    /**
93     * @return The maximum height of this notification.
94     */
95    public int getMaxHeight() {
96        return getHeight();
97    }
98
99    /**
100     * @return The minimum height of this notification.
101     */
102    public int getMinHeight() {
103        return getHeight();
104    }
105
106    /**
107     * Sets the notification as dimmed. The default implementation does nothing.
108     *
109     * @param dimmed Whether the notification should be dimmed.
110     * @param fade Whether an animation should be played to change the state.
111     */
112    public void setDimmed(boolean dimmed, boolean fade) {
113    }
114
115    /**
116     * @return The desired notification height.
117     */
118    public int getIntrinsicHeight() {
119        return getHeight();
120    }
121
122    /**
123     * Sets the amount this view should be clipped from the top. This is used when an expanded
124     * notification is scrolling in the top or bottom stack.
125     *
126     * @param clipTopAmount The amount of pixels this view should be clipped from top.
127     */
128    public void setClipTopAmount(int clipTopAmount) {
129        mClipTopAmount = clipTopAmount;
130    }
131
132    public int getClipTopAmount() {
133        return mClipTopAmount;
134    }
135
136    public void setOnHeightChangedListener(OnHeightChangedListener listener) {
137        mOnHeightChangedListener = listener;
138    }
139
140    /**
141     * @return Whether we can expand this views content.
142     */
143    public boolean isContentExpandable() {
144        return false;
145    }
146
147    public void notifyHeightChanged() {
148        if (mOnHeightChangedListener != null) {
149            mOnHeightChangedListener.onHeightChanged(this);
150        }
151    }
152
153    public boolean isTransparent() {
154        return false;
155    }
156
157    /**
158     * A listener notifying when {@link #getActualHeight} changes.
159     */
160    public interface OnHeightChangedListener {
161        void onHeightChanged(ExpandableView view);
162    }
163}
164