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.View;
22import android.view.animation.Interpolator;
23
24import com.android.systemui.Interpolators;
25
26/**
27 * A common base class for all views in the notification stack scroller which don't have a
28 * background.
29 */
30public abstract class StackScrollerDecorView extends ExpandableView {
31
32    protected View mContent;
33    private boolean mIsVisible;
34    private boolean mAnimating;
35
36    public StackScrollerDecorView(Context context, AttributeSet attrs) {
37        super(context, attrs);
38    }
39
40    @Override
41    protected void onFinishInflate() {
42        super.onFinishInflate();
43        mContent = findContentView();
44        setInvisible();
45    }
46
47    @Override
48    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
49        super.onLayout(changed, left, top, right, bottom);
50        setOutlineProvider(null);
51    }
52
53    @Override
54    public boolean isTransparent() {
55        return true;
56    }
57
58    public void performVisibilityAnimation(boolean nowVisible) {
59        animateText(nowVisible, null /* onFinishedRunnable */);
60    }
61
62    public void performVisibilityAnimation(boolean nowVisible, Runnable onFinishedRunnable) {
63        animateText(nowVisible, onFinishedRunnable);
64    }
65
66    public boolean isVisible() {
67        return mIsVisible || mAnimating;
68    }
69
70    /**
71     * Animate the text to a new visibility.
72     *
73     * @param nowVisible should it now be visible
74     * @param onFinishedRunnable A runnable which should be run when the animation is
75     *        finished.
76     */
77    private void animateText(boolean nowVisible, final Runnable onFinishedRunnable) {
78        if (nowVisible != mIsVisible) {
79            // Animate text
80            float endValue = nowVisible ? 1.0f : 0.0f;
81            Interpolator interpolator;
82            if (nowVisible) {
83                interpolator = Interpolators.ALPHA_IN;
84            } else {
85                interpolator = Interpolators.ALPHA_OUT;
86            }
87            mAnimating = true;
88            mContent.animate()
89                    .alpha(endValue)
90                    .setInterpolator(interpolator)
91                    .setDuration(260)
92                    .withEndAction(new Runnable() {
93                        @Override
94                        public void run() {
95                            mAnimating = false;
96                            if (onFinishedRunnable != null) {
97                                onFinishedRunnable.run();
98                            }
99                        }
100                    });
101            mIsVisible = nowVisible;
102        } else {
103            if (onFinishedRunnable != null) {
104                onFinishedRunnable.run();
105            }
106        }
107    }
108
109    public void setInvisible() {
110        mContent.setAlpha(0.0f);
111        mIsVisible = false;
112    }
113
114    @Override
115    public void performRemoveAnimation(long duration, float translationDirection,
116            Runnable onFinishedRunnable) {
117        // TODO: Use duration
118        performVisibilityAnimation(false);
119    }
120
121    @Override
122    public void performAddAnimation(long delay, long duration) {
123        // TODO: use delay and duration
124        performVisibilityAnimation(true);
125    }
126
127    @Override
128    public boolean hasOverlappingRendering() {
129        return false;
130    }
131
132    public void cancelAnimation() {
133        mContent.animate().cancel();
134    }
135
136    protected abstract View findContentView();
137}
138