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