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.ui;
18 
19 import android.animation.Animator;
20 import android.animation.Animator.AnimatorListener;
21 import android.animation.AnimatorInflater;
22 import android.animation.AnimatorListenerAdapter;
23 import android.content.Context;
24 import android.text.TextUtils;
25 import android.util.AttributeSet;
26 import android.view.View;
27 import android.widget.ImageView;
28 import android.widget.ImageView.ScaleType;
29 import android.widget.LinearLayout;
30 import android.widget.TextView;
31 
32 import com.android.tv.R;
33 import com.android.tv.ui.TunableTvView.BlockScreenType;
34 
35 public class BlockScreenView extends LinearLayout {
36     private View mContainerView;
37     private View mImageContainer;
38     private ImageView mNormalImageView;
39     private ImageView mShrunkenImageView;
40     private View mSpace;
41     private TextView mTextView;
42 
43     private final int mSpacingNormal;
44     private final int mSpacingShrunken;
45 
46     // Animators used for fade in/out of block screen icon.
47     private Animator mFadeIn;
48     private Animator mFadeOut;
49 
BlockScreenView(Context context)50     public BlockScreenView(Context context) {
51         this(context, null, 0);
52     }
53 
BlockScreenView(Context context, AttributeSet attrs)54     public BlockScreenView(Context context, AttributeSet attrs) {
55         this(context, attrs, 0);
56     }
57 
BlockScreenView(Context context, AttributeSet attrs, int defStyle)58     public BlockScreenView(Context context, AttributeSet attrs, int defStyle) {
59         super(context, attrs, defStyle);
60         mSpacingNormal = getResources().getDimensionPixelOffset(
61                 R.dimen.tvview_block_vertical_spacing);
62         mSpacingShrunken = getResources().getDimensionPixelOffset(
63                 R.dimen.shrunken_tvview_block_vertical_spacing);
64     }
65 
66     @Override
onFinishInflate()67     protected void onFinishInflate() {
68         super.onFinishInflate();
69         mContainerView = findViewById(R.id.block_screen_container);
70         mImageContainer = findViewById(R.id.image_container);
71         mNormalImageView = (ImageView) findViewById(R.id.block_screen_icon);
72         mShrunkenImageView = (ImageView) findViewById(R.id.block_screen_shrunken_icon);
73         mSpace = findViewById(R.id.space);
74         mTextView = (TextView) findViewById(R.id.block_screen_text);
75         mFadeIn = AnimatorInflater.loadAnimator(getContext(),
76                 R.animator.tvview_block_screen_fade_in);
77         mFadeIn.setTarget(mContainerView);
78         mFadeOut = AnimatorInflater.loadAnimator(getContext(),
79                 R.animator.tvview_block_screen_fade_out);
80         mFadeOut.setTarget(mContainerView);
81         mFadeOut.addListener(new AnimatorListenerAdapter() {
82             @Override
83             public void onAnimationEnd(Animator animation) {
84                 mContainerView.setVisibility(GONE);
85                 mContainerView.setAlpha(1f);
86             }
87         });
88     }
89 
90     /**
91      * Sets the normal image.
92      */
setImage(int resId)93     public void setImage(int resId) {
94         mNormalImageView.setImageResource(resId);
95         updateSpaceVisibility();
96     }
97 
98     /**
99      * Sets the scale type of the normal image.
100      */
setScaleType(ScaleType scaleType)101     public void setScaleType(ScaleType scaleType) {
102         mNormalImageView.setScaleType(scaleType);
103         updateSpaceVisibility();
104     }
105 
106     /**
107      * Sets the shrunken image.
108      */
setShrunkenImage(int resId)109     public void setShrunkenImage(int resId) {
110         mShrunkenImageView.setImageResource(resId);
111         updateSpaceVisibility();
112     }
113 
114     /**
115      * Show or hide the image of this view.
116      */
setImageVisibility(boolean visible)117     public void setImageVisibility(boolean visible) {
118         mImageContainer.setVisibility(visible ? VISIBLE : GONE);
119         updateSpaceVisibility();
120     }
121 
122     /**
123      * Sets the text message.
124      */
setText(int resId)125     public void setText(int resId) {
126         mTextView.setText(resId);
127         updateSpaceVisibility();
128     }
129 
130     /**
131      * Sets the text message.
132      */
setText(String text)133     public void setText(String text) {
134         mTextView.setText(text);
135         updateSpaceVisibility();
136     }
137 
updateSpaceVisibility()138     private void updateSpaceVisibility() {
139         if (isImageViewVisible() && isTextViewVisible(mTextView)) {
140             mSpace.setVisibility(VISIBLE);
141         } else {
142             mSpace.setVisibility(GONE);
143         }
144     }
145 
isImageViewVisible()146     private boolean isImageViewVisible() {
147         return mImageContainer.getVisibility() == VISIBLE
148                 && (isImageViewVisible(mNormalImageView) || isImageViewVisible(mShrunkenImageView));
149     }
150 
isImageViewVisible(ImageView imageView)151     private static boolean isImageViewVisible(ImageView imageView) {
152         return imageView.getVisibility() != GONE && imageView.getDrawable() != null;
153     }
154 
isTextViewVisible(TextView textView)155     private static boolean isTextViewVisible(TextView textView) {
156         return textView.getVisibility() != GONE && !TextUtils.isEmpty(textView.getText());
157     }
158 
159     /**
160      * Changes the spacing between the image view and the text view according to the
161      * {@code blockScreenType}.
162      */
setSpacing(@lockScreenType int blockScreenType)163     public void setSpacing(@BlockScreenType int blockScreenType) {
164         mSpace.getLayoutParams().height =
165                 blockScreenType == TunableTvView.BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW
166                 ? mSpacingShrunken : mSpacingNormal;
167         requestLayout();
168     }
169 
170     /**
171      * Changes the view layout according to the {@code blockScreenType}.
172      */
onBlockStatusChanged(@lockScreenType int blockScreenType, boolean withAnimation)173     public void onBlockStatusChanged(@BlockScreenType int blockScreenType, boolean withAnimation) {
174         if (!withAnimation) {
175             switch (blockScreenType) {
176                 case TunableTvView.BLOCK_SCREEN_TYPE_NO_UI:
177                     mContainerView.setVisibility(GONE);
178                     break;
179                 case TunableTvView.BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW:
180                     mNormalImageView.setVisibility(GONE);
181                     mShrunkenImageView.setVisibility(VISIBLE);
182                     mContainerView.setVisibility(VISIBLE);
183                     break;
184                 case TunableTvView.BLOCK_SCREEN_TYPE_NORMAL:
185                     mNormalImageView.setVisibility(VISIBLE);
186                     mShrunkenImageView.setVisibility(GONE);
187                     mContainerView.setVisibility(VISIBLE);
188                     break;
189             }
190         } else {
191             switch (blockScreenType) {
192                 case TunableTvView.BLOCK_SCREEN_TYPE_NO_UI:
193                     if (mContainerView.getVisibility() == VISIBLE) {
194                         mFadeOut.start();
195                     }
196                     break;
197                 case TunableTvView.BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW:
198                     mNormalImageView.setVisibility(GONE);
199                     mShrunkenImageView.setVisibility(VISIBLE);
200                     mContainerView.setVisibility(VISIBLE);
201                     if (mContainerView.getVisibility() == GONE) {
202                         mFadeIn.start();
203                     }
204                     break;
205                 case TunableTvView.BLOCK_SCREEN_TYPE_NORMAL:
206                     mNormalImageView.setVisibility(VISIBLE);
207                     mShrunkenImageView.setVisibility(GONE);
208                     mContainerView.setVisibility(VISIBLE);
209                     if (mContainerView.getVisibility() == GONE) {
210                         mFadeIn.start();
211                     }
212                     break;
213             }
214         }
215         updateSpaceVisibility();
216     }
217 
218     /**
219      * Scales the contents view by the given {@code scale}.
220      */
scaleContainerView(float scale)221     public void scaleContainerView(float scale) {
222         mContainerView.setScaleX(scale);
223         mContainerView.setScaleY(scale);
224     }
225 
addFadeOutAnimationListener(AnimatorListener listener)226     public void addFadeOutAnimationListener(AnimatorListener listener) {
227         mFadeOut.addListener(listener);
228     }
229 
230     /**
231      * Ends the currently running animations.
232      */
endAnimations()233     public void endAnimations() {
234         if (mFadeIn != null && mFadeIn.isRunning()) {
235             mFadeIn.end();
236         }
237         if (mFadeOut != null && mFadeOut.isRunning()) {
238             mFadeOut.end();
239         }
240     }
241 }
242