Home | History | Annotate | Download | only in menu
      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.content.Context;
     20 import android.graphics.Bitmap;
     21 import android.support.annotation.Nullable;
     22 import android.text.TextUtils;
     23 import android.util.AttributeSet;
     24 import android.util.Log;
     25 import android.view.View;
     26 import android.view.ViewGroup;
     27 import android.widget.ImageView;
     28 import android.widget.ProgressBar;
     29 import android.widget.TextView;
     30 
     31 import com.android.tv.MainActivity;
     32 import com.android.tv.R;
     33 import com.android.tv.data.Channel;
     34 import com.android.tv.data.Program;
     35 import com.android.tv.parental.ParentalControlSettings;
     36 import com.android.tv.util.ImageLoader;
     37 
     38 /**
     39  * A view to render channel card.
     40  */
     41 public class ChannelCardView extends BaseCardView<Channel> {
     42     private static final String TAG = MenuView.TAG;
     43     private static final boolean DEBUG = MenuView.DEBUG;
     44 
     45     private final float mCardHeight;
     46     private final float mExtendedCardHeight;
     47     private final float mProgramNameViewHeight;
     48     private final float mExtendedTextViewCardHeight;
     49     private final int mCardImageWidth;
     50     private final int mCardImageHeight;
     51 
     52     private ImageView mImageView;
     53     private View mGradientView;
     54     private TextView mChannelNumberNameView;
     55     private ProgressBar mProgressBar;
     56     private TextView mMetaViewFocused;
     57     private TextView mMetaViewUnfocused;
     58     private Channel mChannel;
     59     private Program mProgram;
     60     private boolean mExtendViewOnFocus;
     61     private final MainActivity mMainActivity;
     62 
     63     public ChannelCardView(Context context) {
     64         this(context, null);
     65     }
     66 
     67     public ChannelCardView(Context context, AttributeSet attrs) {
     68         this(context, attrs, 0);
     69     }
     70 
     71     public ChannelCardView(Context context, AttributeSet attrs, int defStyle) {
     72         super(context, attrs, defStyle);
     73 
     74         mCardImageWidth = getResources().getDimensionPixelSize(R.dimen.card_image_layout_width);
     75         mCardImageHeight = getResources().getDimensionPixelSize(R.dimen.card_image_layout_height);
     76         mCardHeight = getResources().getDimensionPixelSize(R.dimen.card_layout_height);
     77         mExtendedCardHeight = getResources().getDimensionPixelSize(
     78                 R.dimen.card_layout_height_extended);
     79         mProgramNameViewHeight = getResources().getDimensionPixelSize(
     80                 R.dimen.card_meta_layout_height);
     81         mExtendedTextViewCardHeight = getResources().getDimensionPixelOffset(
     82                 R.dimen.card_meta_layout_height_extended);
     83 
     84         mMainActivity = (MainActivity) context;
     85     }
     86 
     87     @Override
     88     protected void onFinishInflate() {
     89         super.onFinishInflate();
     90         mImageView = (ImageView) findViewById(R.id.image);
     91         mGradientView = findViewById(R.id.image_gradient);
     92         mChannelNumberNameView = (TextView) findViewById(R.id.channel_number_and_name);
     93         mMetaViewFocused = (TextView) findViewById(R.id.channel_title_focused);
     94         mMetaViewUnfocused = (TextView) findViewById(R.id.channel_title_unfocused);
     95         mProgressBar = (ProgressBar) findViewById(R.id.progress);
     96     }
     97 
     98     @Override
     99     public void onBind(Channel channel, boolean selected) {
    100         if (DEBUG) {
    101             Log.d(TAG, "onBind(channelName=" + channel.getDisplayName() + ", selected=" + selected
    102                     + ")");
    103         }
    104         mChannel = channel;
    105         mProgram = null;
    106         if (TextUtils.isEmpty(mChannel.getDisplayName())) {
    107             mChannelNumberNameView.setText(mChannel.getDisplayNumber());
    108         } else {
    109             mChannelNumberNameView.setText(mChannel.getDisplayNumber() + " "
    110                     + mChannel.getDisplayName());
    111         }
    112         mChannelNumberNameView.setVisibility(VISIBLE);
    113         mImageView.setImageResource(R.drawable.ic_recent_thumbnail_default);
    114         mImageView.setBackgroundResource(R.color.channel_card);
    115         mGradientView.setVisibility(View.GONE);
    116         mProgressBar.setVisibility(GONE);
    117 
    118         setMetaViewEnabled(true);
    119         if (mMainActivity.getParentalControlSettings().isParentalControlsEnabled()
    120                 && mChannel.isLocked()) {
    121             setMetaViewText(R.string.program_title_for_blocked_channel);
    122             return;
    123         } else {
    124             setMetaViewText("");
    125         }
    126 
    127         updateProgramInformation();
    128         mMetaViewFocused.measure(
    129                 MeasureSpec.makeMeasureSpec(mCardImageWidth, MeasureSpec.EXACTLY),
    130                 MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    131         if (mExtendViewOnFocus = mMetaViewFocused.getLineCount() > 1) {
    132             setMetaViewFocusedAlpha(selected ? 1f : 0f);
    133         } else {
    134             setMetaViewFocusedAlpha(1f);
    135         }
    136 
    137         // Call super.onBind() at the end in order to make getCardHeight() return a proper value.
    138         super.onBind(channel, selected);
    139     }
    140 
    141     private static ImageLoader.ImageLoaderCallback<ChannelCardView> createProgramPosterArtCallback(
    142             ChannelCardView cardView, final Program program) {
    143         return new ImageLoader.ImageLoaderCallback<ChannelCardView>(cardView) {
    144             @Override
    145             public void onBitmapLoaded(ChannelCardView cardView, @Nullable Bitmap posterArt) {
    146                 if (posterArt == null || cardView.mProgram == null
    147                         || program.getChannelId() != cardView.mProgram.getChannelId()
    148                         || program.getChannelId() != cardView.mChannel.getId()) {
    149                     return;
    150                 }
    151                 cardView.updatePosterArt(posterArt);
    152             }
    153         };
    154     }
    155 
    156     private void updatePosterArt(Bitmap posterArt) {
    157         mImageView.setImageBitmap(posterArt);
    158         mGradientView.setVisibility(View.VISIBLE);
    159     }
    160 
    161     @Override
    162     protected void onFocusAnimationStart(boolean selected) {
    163         if (mExtendViewOnFocus) {
    164             setMetaViewFocusedAlpha(selected ? 1f : 0f);
    165         }
    166     }
    167 
    168     @Override
    169     protected void onSetFocusAnimatedValue(float animatedValue) {
    170         super.onSetFocusAnimatedValue(animatedValue);
    171         if (mExtendViewOnFocus) {
    172             ViewGroup.LayoutParams params = mMetaViewUnfocused.getLayoutParams();
    173             params.height = Math.round(mProgramNameViewHeight
    174                     + (mExtendedTextViewCardHeight - mProgramNameViewHeight) * animatedValue);
    175             setMetaViewLayoutParams(params);
    176             setMetaViewFocusedAlpha(animatedValue);
    177         }
    178     }
    179 
    180     @Override
    181     protected float getCardHeight() {
    182         return (mExtendViewOnFocus && isFocused()) ? mExtendedCardHeight : mCardHeight;
    183     }
    184 
    185     private void updateProgramInformation() {
    186         if (mChannel == null) {
    187             return;
    188         }
    189         mProgram = mMainActivity.getProgramDataManager().getCurrentProgram(mChannel.getId());
    190         if (mProgram == null || TextUtils.isEmpty(mProgram.getTitle())) {
    191             setMetaViewEnabled(false);
    192             setMetaViewText(R.string.program_title_for_no_information);
    193         } else {
    194             setMetaViewText(mProgram.getTitle());
    195         }
    196 
    197         if (mProgram == null) {
    198             return;
    199         }
    200 
    201         long startTime = mProgram.getStartTimeUtcMillis();
    202         long endTime = mProgram.getEndTimeUtcMillis();
    203         long currTime = System.currentTimeMillis();
    204         mProgressBar.setVisibility(View.VISIBLE);
    205         if (currTime <= startTime) {
    206             mProgressBar.setProgress(0);
    207         } else if (currTime >= endTime) {
    208             mProgressBar.setProgress(100);
    209         } else {
    210             mProgressBar.setProgress((int) (100 * (currTime - startTime) / (endTime - startTime)));
    211         }
    212 
    213         if (!(getContext() instanceof MainActivity)) {
    214             Log.e(TAG, "Fails to check program's content rating.");
    215             return;
    216         }
    217         ParentalControlSettings parental = mMainActivity.getParentalControlSettings();
    218         if ((!parental.isParentalControlsEnabled()
    219                 || !parental.isRatingBlocked(mProgram.getContentRatings()))
    220                 && !TextUtils.isEmpty(mProgram.getPosterArtUri())) {
    221             mProgram.loadPosterArt(getContext(), mCardImageWidth, mCardImageHeight,
    222                     createProgramPosterArtCallback(this, mProgram));
    223         }
    224     }
    225 
    226     private void setMetaViewLayoutParams(ViewGroup.LayoutParams params) {
    227         mMetaViewFocused.setLayoutParams(params);
    228         mMetaViewUnfocused.setLayoutParams(params);
    229     }
    230 
    231     private void setMetaViewText(String text) {
    232         mMetaViewFocused.setText(text);
    233         mMetaViewUnfocused.setText(text);
    234     }
    235 
    236     private void setMetaViewText(int resId) {
    237         mMetaViewFocused.setText(resId);
    238         mMetaViewUnfocused.setText(resId);
    239     }
    240 
    241     private void setMetaViewEnabled(boolean enabled) {
    242         mMetaViewFocused.setEnabled(enabled);
    243         mMetaViewUnfocused.setEnabled(enabled);
    244     }
    245 
    246     private void setMetaViewFocusedAlpha(float focusedAlpha) {
    247         mMetaViewFocused.setAlpha(focusedAlpha);
    248         mMetaViewUnfocused.setAlpha(1f - focusedAlpha);
    249     }
    250 }
    251