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