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
17package com.android.tv.ui;
18
19import android.animation.Animator;
20import android.animation.Animator.AnimatorListener;
21import android.animation.AnimatorInflater;
22import android.animation.AnimatorListenerAdapter;
23import android.content.Context;
24import android.text.TextUtils;
25import android.util.AttributeSet;
26import android.view.View;
27import android.widget.ImageView;
28import android.widget.ImageView.ScaleType;
29import android.widget.LinearLayout;
30import android.widget.TextView;
31
32import com.android.tv.R;
33import com.android.tv.ui.TunableTvView.BlockScreenType;
34
35public 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
50    public BlockScreenView(Context context) {
51        this(context, null, 0);
52    }
53
54    public BlockScreenView(Context context, AttributeSet attrs) {
55        this(context, attrs, 0);
56    }
57
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
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     */
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     */
101    public void setScaleType(ScaleType scaleType) {
102        mNormalImageView.setScaleType(scaleType);
103        updateSpaceVisibility();
104    }
105
106    /**
107     * Sets the shrunken image.
108     */
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     */
117    public void setImageVisibility(boolean visible) {
118        mImageContainer.setVisibility(visible ? VISIBLE : GONE);
119        updateSpaceVisibility();
120    }
121
122    /**
123     * Sets the text message.
124     */
125    public void setText(int resId) {
126        mTextView.setText(resId);
127        updateSpaceVisibility();
128    }
129
130    /**
131     * Sets the text message.
132     */
133    public void setText(String text) {
134        mTextView.setText(text);
135        updateSpaceVisibility();
136    }
137
138    private void updateSpaceVisibility() {
139        if (isImageViewVisible() && isTextViewVisible(mTextView)) {
140            mSpace.setVisibility(VISIBLE);
141        } else {
142            mSpace.setVisibility(GONE);
143        }
144    }
145
146    private boolean isImageViewVisible() {
147        return mImageContainer.getVisibility() == VISIBLE
148                && (isImageViewVisible(mNormalImageView) || isImageViewVisible(mShrunkenImageView));
149    }
150
151    private static boolean isImageViewVisible(ImageView imageView) {
152        return imageView.getVisibility() != GONE && imageView.getDrawable() != null;
153    }
154
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     */
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     */
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     */
221    public void scaleContainerView(float scale) {
222        mContainerView.setScaleX(scale);
223        mContainerView.setScaleY(scale);
224    }
225
226    public void addFadeOutAnimationListener(AnimatorListener listener) {
227        mFadeOut.addListener(listener);
228    }
229
230    /**
231     * Ends the currently running animations.
232     */
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