[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.content.Context;
22import android.content.res.TypedArray;
23import android.util.AttributeSet;
24import android.view.LayoutInflater;
25import android.view.View.OnFocusChangeListener;
26import android.view.View;
27import android.widget.ImageView;
28import android.widget.RelativeLayout;
29import android.widget.TextView;
30
31import com.android.systemui.R;
32
33/**
34 * A view containing PIP controls including fullscreen, close, and media controls.
35 */
36public class PipControlButtonView extends RelativeLayout {
37    private OnFocusChangeListener mFocusChangeListener;
38    private ImageView mIconImageView;
39    ImageView mButtonImageView;
40    private TextView mDescriptionTextView;
41    private Animator mTextFocusGainAnimator;
42    private Animator mButtonFocusGainAnimator;
43    private Animator mTextFocusLossAnimator;
44    private Animator mButtonFocusLossAnimator;
45
46    private final OnFocusChangeListener mInternalFocusChangeListener =
47            new OnFocusChangeListener() {
48                @Override
49                public void onFocusChange(View v, boolean hasFocus) {
50                    if (hasFocus) {
51                        startFocusGainAnimation();
52                    } else {
53                        startFocusLossAnimation();
54                    }
55
56                    if (mFocusChangeListener != null) {
57                        mFocusChangeListener.onFocusChange(PipControlButtonView.this, hasFocus);
58                    }
59                }
60            };
61
62    public PipControlButtonView(Context context) {
63        this(context, null, 0, 0);
64    }
65
66    public PipControlButtonView(Context context, AttributeSet attrs) {
67        this(context, attrs, 0, 0);
68    }
69
70    public PipControlButtonView(Context context, AttributeSet attrs, int defStyleAttr) {
71        this(context, attrs, defStyleAttr, 0);
72    }
73
74    public PipControlButtonView(
75            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
76        super(context, attrs, defStyleAttr, defStyleRes);
77        LayoutInflater inflater = (LayoutInflater) getContext()
78                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
79        inflater.inflate(R.layout.tv_pip_control_button, this);
80
81        mIconImageView = (ImageView) findViewById(R.id.icon);
82        mButtonImageView = (ImageView) findViewById(R.id.button);
83        mDescriptionTextView = (TextView) findViewById(R.id.desc);
84
85        int[] values = new int[] {android.R.attr.src, android.R.attr.text};
86        TypedArray typedArray =
87            context.obtainStyledAttributes(attrs, values, defStyleAttr, defStyleRes);
88
89        setImageResource(typedArray.getResourceId(0, 0));
90        setText(typedArray.getResourceId(1, 0));
91
92        typedArray.recycle();
93    }
94
95    @Override
96    public void onFinishInflate() {
97        super.onFinishInflate();
98        mButtonImageView.setOnFocusChangeListener(mInternalFocusChangeListener);
99
100        mTextFocusGainAnimator = AnimatorInflater.loadAnimator(getContext(),
101                R.anim.tv_pip_controls_focus_gain_animation);
102        mTextFocusGainAnimator.setTarget(mDescriptionTextView);
103        mButtonFocusGainAnimator = AnimatorInflater.loadAnimator(getContext(),
104                R.anim.tv_pip_controls_focus_gain_animation);
105        mButtonFocusGainAnimator.setTarget(mButtonImageView);
106
107        mTextFocusLossAnimator = AnimatorInflater.loadAnimator(getContext(),
108                R.anim.tv_pip_controls_focus_loss_animation);
109        mTextFocusLossAnimator.setTarget(mDescriptionTextView);
110        mButtonFocusLossAnimator = AnimatorInflater.loadAnimator(getContext(),
111                R.anim.tv_pip_controls_focus_loss_animation);
112        mButtonFocusLossAnimator.setTarget(mButtonImageView);
113    }
114
115    @Override
116    public void setOnClickListener(OnClickListener listener) {
117        mButtonImageView.setOnClickListener(listener);
118    }
119
120    @Override
121    public void setOnFocusChangeListener(OnFocusChangeListener listener) {
122        mFocusChangeListener = listener;
123    }
124
125    /**
126     * Sets the drawable for the button with the given resource id.
127     */
128    public void setImageResource(int resId) {
129        mIconImageView.setImageResource(resId);
130    }
131
132    /**
133     * Sets the text for description the with the given resource id.
134     */
135    public void setText(int resId) {
136        mButtonImageView.setContentDescription(getContext().getString(resId));
137        mDescriptionTextView.setText(resId);
138    }
139
140    private static void cancelAnimator(Animator animator) {
141        if (animator.isStarted()) {
142            animator.cancel();
143        }
144    }
145
146    /**
147     * Starts the focus gain animation.
148     */
149    public void startFocusGainAnimation() {
150        cancelAnimator(mButtonFocusLossAnimator);
151        cancelAnimator(mTextFocusLossAnimator);
152        mTextFocusGainAnimator.start();
153        if (mButtonImageView.getAlpha() < 1f) {
154            // If we had faded out the ripple drawable, run our manual focus change animation.
155            // See the comment at {@link #startFocusLossAnimation()} for the reason of manual
156            // animator.
157            mButtonFocusGainAnimator.start();
158        }
159    }
160
161    /**
162     * Starts the focus loss animation.
163     */
164    public void startFocusLossAnimation() {
165        cancelAnimator(mButtonFocusGainAnimator);
166        cancelAnimator(mTextFocusGainAnimator);
167        mTextFocusLossAnimator.start();
168        if (mButtonImageView.hasFocus()) {
169            // Button uses ripple that has the default animation for the focus changes.
170            // Howevever, it doesn't expose the API to fade out while it is focused,
171            // so we should manually run the fade out animation when PIP controls row loses focus.
172            mButtonFocusLossAnimator.start();
173        }
174    }
175
176    /**
177     * Resets to initial state.
178     */
179    public void reset() {
180        cancelAnimator(mButtonFocusGainAnimator);
181        cancelAnimator(mTextFocusGainAnimator);
182        cancelAnimator(mButtonFocusLossAnimator);
183        cancelAnimator(mTextFocusLossAnimator);
184        mButtonImageView.setAlpha(1f);
185        mDescriptionTextView.setAlpha(mButtonImageView.hasFocus() ? 1f : 0f);
186    }
187}
188