[go: nahoru, domu]

1/*
2 * Copyright (C) 2016 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.tv.pip;
18
19import android.animation.Animator;
20import android.animation.AnimatorInflater;
21import android.animation.AnimatorListenerAdapter;
22import android.animation.AnimatorSet;
23import android.content.Context;
24import android.graphics.Rect;
25import android.util.AttributeSet;
26import android.view.KeyEvent;
27import android.view.View;
28import android.view.View.OnFocusChangeListener;
29import android.widget.FrameLayout;
30
31import com.android.systemui.R;
32
33import static com.android.systemui.tv.pip.PipManager.PLAYBACK_STATE_PLAYING;
34import static com.android.systemui.tv.pip.PipManager.PLAYBACK_STATE_PAUSED;
35import static com.android.systemui.tv.pip.PipManager.PLAYBACK_STATE_UNAVAILABLE;
36
37/**
38 * An FrameLayout that contains {@link PipControlsView} with its scrim.
39 */
40public class PipRecentsControlsView extends FrameLayout {
41    /**
42     * An interface to listen user action.
43     */
44    public interface Listener extends PipControlsView.Listener {
45        /**
46         * Called when an user presses BACK key and up.
47         */
48        abstract void onBackPressed();
49    }
50
51    private final PipManager mPipManager = PipManager.getInstance();
52    private Listener mListener;
53    private PipControlsView mPipControlsView;
54    private View mScrim;
55    private Animator mFocusGainAnimator;
56    private AnimatorSet mFocusLossAnimatorSet;
57
58    public PipRecentsControlsView(Context context) {
59        this(context, null, 0, 0);
60    }
61
62    public PipRecentsControlsView(Context context, AttributeSet attrs) {
63        this(context, attrs, 0, 0);
64    }
65
66    public PipRecentsControlsView(Context context, AttributeSet attrs, int defStyleAttr) {
67        this(context, attrs, defStyleAttr, 0);
68    }
69
70    public PipRecentsControlsView(
71            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
72        super(context, attrs, defStyleAttr, defStyleRes);
73    }
74
75    @Override
76    public void onFinishInflate() {
77        super.onFinishInflate();
78
79        mPipControlsView = (PipControlsView) findViewById(R.id.pip_control_contents);
80        mScrim = findViewById(R.id.scrim);
81
82        mFocusGainAnimator = loadAnimator(mPipControlsView,
83                R.anim.tv_pip_controls_in_recents_focus_gain_animation);
84
85        mFocusLossAnimatorSet = new AnimatorSet();
86        mFocusLossAnimatorSet.playSequentially(
87                loadAnimator(mPipControlsView,
88                        R.anim.tv_pip_controls_in_recents_focus_loss_animation),
89                loadAnimator(mScrim, R.anim.tv_pip_controls_in_recents_scrim_fade_in_animation));
90
91        Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
92        setPadding(0, pipBounds.bottom, 0, 0);
93    }
94
95    private Animator loadAnimator(View view, int animatorResId) {
96        Animator animator = AnimatorInflater.loadAnimator(getContext(), animatorResId);
97        animator.setTarget(view);
98        return animator;
99    }
100
101    /**
102     * Starts focus gain animation.
103     */
104    public void startFocusGainAnimation() {
105        // Hides the scrim view as soon as possible, before the PIP resize animation starts.
106        // If we don't, PIP will be moved down a bit and a gap between the scrim and PIP will be
107        // shown at the bottom of the PIP.
108        mScrim.setAlpha(0);
109        PipControlButtonView focus = mPipControlsView.getFocusedButton();
110        if (focus != null) {
111            focus.startFocusGainAnimation();
112        }
113        startAnimator(mFocusGainAnimator, mFocusLossAnimatorSet);
114    }
115
116    /**
117     * Starts focus loss animation.
118     */
119    public void startFocusLossAnimation() {
120        PipControlButtonView focus = mPipControlsView.getFocusedButton();
121        if (focus != null) {
122            focus.startFocusLossAnimation();
123        }
124        startAnimator(mFocusLossAnimatorSet, mFocusGainAnimator);
125    }
126
127    /**
128     * Resets the view to the initial state. (i.e. end of the focus gain)
129     */
130    public void reset() {
131        cancelAnimator(mFocusGainAnimator);
132        cancelAnimator(mFocusLossAnimatorSet);
133
134        // Reset to initial state (i.e. end of focused)
135        mScrim.setAlpha(0);
136        mPipControlsView.setTranslationY(0);
137        mPipControlsView.setScaleX(1);
138        mPipControlsView.setScaleY(1);
139        mPipControlsView.reset();
140    }
141
142    private static void startAnimator(Animator animator, Animator previousAnimator) {
143        cancelAnimator(previousAnimator);
144        if (!animator.isStarted()) {
145            animator.start();
146        }
147    }
148
149    private static void cancelAnimator(Animator animator) {
150        if (animator.isStarted()) {
151            animator.cancel();
152        }
153    }
154
155    /**
156     * Sets listeners.
157     */
158    public void setListener(Listener listener) {
159        mPipControlsView.setListener(listener);
160    }
161
162    @Override
163    public boolean dispatchKeyEvent(KeyEvent event) {
164        if (!event.isCanceled()) {
165            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
166                    && event.getAction() == KeyEvent.ACTION_UP) {
167                if (mPipControlsView.mListener != null) {
168                    ((PipRecentsControlsView.Listener) mPipControlsView.mListener).onBackPressed();
169                }
170                return true;
171            } else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {
172                if (event.getAction() == KeyEvent.ACTION_DOWN) {
173                    mPipManager.getPipRecentsOverlayManager().clearFocus();
174                }
175                // Consume the down event always to prevent warning logs from ViewRootImpl.
176                return true;
177            }
178        }
179        return super.dispatchKeyEvent(event);
180    }
181}
182