1 /*
2  * Copyright (C) 2015 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 
17 package com.android.tv.menu;
18 
19 import android.R.integer;
20 import android.animation.ValueAnimator;
21 import android.content.Context;
22 import android.text.TextUtils;
23 import android.util.AttributeSet;
24 import android.view.View;
25 import android.view.accessibility.AccessibilityNodeInfo;
26 import android.widget.FrameLayout;
27 import android.widget.ImageView;
28 import android.widget.TextView;
29 import com.android.tv.R;
30 
31 public class PlayControlsButton extends FrameLayout {
32     private static final float ALPHA_ENABLED = 1.0f;
33     private static final float ALPHA_DISABLED = 0.3f;
34 
35     private final ImageView mButton;
36     private final ImageView mIcon;
37     private final TextView mLabel;
38     private final long mFocusAnimationTimeMs;
39     private final int mIconColor;
40     private int mIconFocusedColor;
41 
42     private int mImageResourceId;
43     private int mTintColor;
44 
PlayControlsButton(Context context)45     public PlayControlsButton(Context context) {
46         this(context, null);
47     }
48 
PlayControlsButton(Context context, AttributeSet attrs)49     public PlayControlsButton(Context context, AttributeSet attrs) {
50         this(context, attrs, 0);
51     }
52 
PlayControlsButton(Context context, AttributeSet attrs, int defStyleAttr)53     public PlayControlsButton(Context context, AttributeSet attrs, int defStyleAttr) {
54         this(context, attrs, defStyleAttr, 0);
55     }
56 
PlayControlsButton( Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)57     public PlayControlsButton(
58             Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
59         super(context, attrs, defStyleAttr, defStyleRes);
60         inflate(context, R.layout.play_controls_button, this);
61         mButton = (ImageView) findViewById(R.id.button);
62         mIcon = (ImageView) findViewById(R.id.icon);
63         mLabel = (TextView) findViewById(R.id.label);
64         mFocusAnimationTimeMs = context.getResources().getInteger(integer.config_shortAnimTime);
65         mIconColor = context.getResources().getColor(R.color.play_controls_icon_color);
66         mIconFocusedColor = mIconColor;
67     }
68 
69     /** Sets the resource ID of the image to be displayed in the center of this control. */
setImageResId(int imageResId)70     public void setImageResId(int imageResId) {
71         int newTintColor = hasFocus() ? mIconFocusedColor : mIconColor;
72         if (mImageResourceId != imageResId) {
73             mImageResourceId = imageResId;
74             mIcon.setImageResource(imageResId);
75             updateTint(newTintColor);
76         } else if (newTintColor != mTintColor) {
77             updateTint(newTintColor);
78         }
79     }
80 
updateTint(int tintColor)81     private void updateTint(int tintColor) {
82         mTintColor = tintColor;
83         // Since on focus changing, icons' color should be switched with animation,
84         // as a result, selectors cannot be used to switch colors in this case.
85         mIcon.getDrawable().setTint(tintColor);
86     }
87 
88     /** Sets an action which is to be run when the button is clicked. */
setAction(final Runnable clickAction)89     public void setAction(final Runnable clickAction) {
90         mButton.setOnClickListener(
91                 new OnClickListener() {
92                     @Override
93                     public void onClick(View view) {
94                         clickAction.run();
95                     }
96                 });
97     }
98 
99     /** Sets the icon's color should change to when the button is on focus. */
setFocusedIconColor(int color)100     public void setFocusedIconColor(int color) {
101         final ValueAnimator valueAnimator = ValueAnimator.ofArgb(mIconColor, color);
102         valueAnimator.addUpdateListener(
103                 new ValueAnimator.AnimatorUpdateListener() {
104                     @Override
105                     public void onAnimationUpdate(final ValueAnimator animator) {
106                         mIcon.getDrawable().setTint((int) animator.getAnimatedValue());
107                     }
108                 });
109         valueAnimator.setDuration(mFocusAnimationTimeMs);
110         mButton.setOnFocusChangeListener(
111                 new View.OnFocusChangeListener() {
112                     @Override
113                     public void onFocusChange(View v, boolean hasFocus) {
114                         if (hasFocus) {
115                             valueAnimator.start();
116                         } else {
117                             valueAnimator.reverse();
118                         }
119                     }
120                 });
121         mIconFocusedColor = color;
122     }
123 
setLabel(String label)124     public void setLabel(String label) {
125         if (TextUtils.isEmpty(label)) {
126             mIcon.setVisibility(View.VISIBLE);
127             mLabel.setVisibility(View.GONE);
128         } else {
129             mIcon.setVisibility(View.GONE);
130             mLabel.setVisibility(View.VISIBLE);
131             if (!TextUtils.equals(mLabel.getText(), label)) {
132                 mLabel.setText(label);
133             }
134         }
135     }
136 
hideRippleAnimation()137     public void hideRippleAnimation() {
138         mButton.getDrawable().jumpToCurrentState();
139     }
140 
141     @Override
setEnabled(boolean enabled)142     public void setEnabled(boolean enabled) {
143         super.setEnabled(enabled);
144         mButton.setEnabled(enabled);
145         mButton.setFocusable(enabled);
146         mIcon.setEnabled(enabled);
147         mIcon.setAlpha(enabled ? ALPHA_ENABLED : ALPHA_DISABLED);
148         mLabel.setEnabled(enabled);
149     }
150 
151     /** Request focus and accessibility focus to the button */
requestFocusWithAccessibility()152     public boolean requestFocusWithAccessibility() {
153         return mButton.requestFocus() &&
154                 mButton.performAccessibilityAction(
155                         AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
156     }
157 }
158