Home | History | Annotate | Download | only in list
      1 /*
      2  * Copyright (C) 2016 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.dvr.ui.list;
     18 
     19 import android.animation.ValueAnimator;
     20 import android.content.Context;
     21 import android.graphics.drawable.Drawable;
     22 import android.support.v17.leanback.widget.RowPresenter;
     23 import android.view.LayoutInflater;
     24 import android.view.View;
     25 import android.view.View.OnClickListener;
     26 import android.view.View.OnFocusChangeListener;
     27 import android.view.ViewGroup;
     28 import android.view.animation.DecelerateInterpolator;
     29 import android.widget.TextView;
     30 import com.android.tv.R;
     31 import com.android.tv.TvSingletons;
     32 import com.android.tv.dvr.data.SeriesRecording;
     33 import com.android.tv.dvr.ui.DvrUiHelper;
     34 import com.android.tv.dvr.ui.list.SchedulesHeaderRow.SeriesRecordingHeaderRow;
     35 
     36 /** A base class for RowPresenter for {@link SchedulesHeaderRow} */
     37 abstract class SchedulesHeaderRowPresenter extends RowPresenter {
     38     private Context mContext;
     39 
     40     public SchedulesHeaderRowPresenter(Context context) {
     41         setHeaderPresenter(null);
     42         setSelectEffectEnabled(false);
     43         mContext = context;
     44     }
     45 
     46     /** Returns the context. */
     47     Context getContext() {
     48         return mContext;
     49     }
     50 
     51     /** A ViewHolder for {@link SchedulesHeaderRow}. */
     52     public static class SchedulesHeaderRowViewHolder extends RowPresenter.ViewHolder {
     53         private TextView mTitle;
     54         private TextView mDescription;
     55 
     56         public SchedulesHeaderRowViewHolder(Context context, ViewGroup parent) {
     57             super(
     58                     LayoutInflater.from(context)
     59                             .inflate(R.layout.dvr_schedules_header, parent, false));
     60             mTitle = (TextView) view.findViewById(R.id.header_title);
     61             mDescription = (TextView) view.findViewById(R.id.header_description);
     62         }
     63     }
     64 
     65     @Override
     66     protected void onBindRowViewHolder(RowPresenter.ViewHolder viewHolder, Object item) {
     67         super.onBindRowViewHolder(viewHolder, item);
     68         SchedulesHeaderRowViewHolder headerViewHolder = (SchedulesHeaderRowViewHolder) viewHolder;
     69         SchedulesHeaderRow header = (SchedulesHeaderRow) item;
     70         headerViewHolder.mTitle.setText(header.getTitle());
     71         headerViewHolder.mDescription.setText(header.getDescription());
     72     }
     73 
     74     /** A presenter for {@link SchedulesHeaderRow.DateHeaderRow}. */
     75     public static class DateHeaderRowPresenter extends SchedulesHeaderRowPresenter {
     76         public DateHeaderRowPresenter(Context context) {
     77             super(context);
     78         }
     79 
     80         @Override
     81         protected ViewHolder createRowViewHolder(ViewGroup parent) {
     82             return new DateHeaderRowViewHolder(getContext(), parent);
     83         }
     84 
     85         /** A ViewHolder for {@link SchedulesHeaderRow.DateHeaderRow}. */
     86         public static class DateHeaderRowViewHolder extends SchedulesHeaderRowViewHolder {
     87             public DateHeaderRowViewHolder(Context context, ViewGroup parent) {
     88                 super(context, parent);
     89             }
     90         }
     91     }
     92 
     93     /** A presenter for {@link SeriesRecordingHeaderRow}. */
     94     public static class SeriesRecordingHeaderRowPresenter extends SchedulesHeaderRowPresenter {
     95         private final boolean mLtr;
     96         private final Drawable mSettingsDrawable;
     97         private final Drawable mCancelDrawable;
     98         private final Drawable mResumeDrawable;
     99 
    100         private final String mSettingsInfo;
    101         private final String mCancelAllInfo;
    102         private final String mResumeInfo;
    103 
    104         public SeriesRecordingHeaderRowPresenter(Context context) {
    105             super(context);
    106             mLtr =
    107                     context.getResources().getConfiguration().getLayoutDirection()
    108                             == View.LAYOUT_DIRECTION_LTR;
    109             mSettingsDrawable = context.getDrawable(R.drawable.ic_settings);
    110             mCancelDrawable = context.getDrawable(R.drawable.ic_dvr_cancel_large);
    111             mResumeDrawable = context.getDrawable(R.drawable.ic_record_start);
    112             mSettingsInfo = context.getString(R.string.dvr_series_schedules_settings);
    113             mCancelAllInfo = context.getString(R.string.dvr_series_schedules_stop);
    114             mResumeInfo = context.getString(R.string.dvr_series_schedules_start);
    115         }
    116 
    117         @Override
    118         protected ViewHolder createRowViewHolder(ViewGroup parent) {
    119             return new SeriesHeaderRowViewHolder(getContext(), parent);
    120         }
    121 
    122         @Override
    123         protected void onBindRowViewHolder(RowPresenter.ViewHolder viewHolder, Object item) {
    124             super.onBindRowViewHolder(viewHolder, item);
    125             SeriesHeaderRowViewHolder headerViewHolder = (SeriesHeaderRowViewHolder) viewHolder;
    126             SeriesRecordingHeaderRow header = (SeriesRecordingHeaderRow) item;
    127             headerViewHolder.mSeriesSettingsButton.setVisibility(
    128                     header.getSeriesRecording().isStopped() ? View.INVISIBLE : View.VISIBLE);
    129             headerViewHolder.mSeriesSettingsButton.setText(mSettingsInfo);
    130             setTextDrawable(headerViewHolder.mSeriesSettingsButton, mSettingsDrawable);
    131             if (header.getSeriesRecording().isStopped()) {
    132                 headerViewHolder.mToggleStartStopButton.setText(mResumeInfo);
    133                 setTextDrawable(headerViewHolder.mToggleStartStopButton, mResumeDrawable);
    134             } else {
    135                 headerViewHolder.mToggleStartStopButton.setText(mCancelAllInfo);
    136                 setTextDrawable(headerViewHolder.mToggleStartStopButton, mCancelDrawable);
    137             }
    138             headerViewHolder.mSeriesSettingsButton.setOnClickListener(
    139                     new OnClickListener() {
    140                         @Override
    141                         public void onClick(View view) {
    142                             DvrUiHelper.startSeriesSettingsActivity(
    143                                     getContext(),
    144                                     header.getSeriesRecording().getId(),
    145                                     header.getPrograms(),
    146                                     false,
    147                                     false,
    148                                     false,
    149                                     null);
    150                         }
    151                     });
    152             headerViewHolder.mToggleStartStopButton.setOnClickListener(
    153                     new OnClickListener() {
    154                         @Override
    155                         public void onClick(View view) {
    156                             if (header.getSeriesRecording().isStopped()) {
    157                                 // Reset priority to the highest.
    158                                 SeriesRecording seriesRecording =
    159                                         SeriesRecording.buildFrom(header.getSeriesRecording())
    160                                                 .setPriority(
    161                                                         TvSingletons.getSingletons(getContext())
    162                                                                 .getDvrScheduleManager()
    163                                                                 .suggestNewSeriesPriority())
    164                                                 .build();
    165                                 TvSingletons.getSingletons(getContext())
    166                                         .getDvrManager()
    167                                         .updateSeriesRecording(seriesRecording);
    168                                 DvrUiHelper.startSeriesSettingsActivity(
    169                                         getContext(),
    170                                         header.getSeriesRecording().getId(),
    171                                         header.getPrograms(),
    172                                         false,
    173                                         false,
    174                                         false,
    175                                         null);
    176                             } else {
    177                                 DvrUiHelper.showCancelAllSeriesRecordingDialog(
    178                                         (DvrSchedulesActivity) view.getContext(),
    179                                         header.getSeriesRecording());
    180                             }
    181                         }
    182                     });
    183         }
    184 
    185         private void setTextDrawable(TextView textView, Drawable drawableStart) {
    186             textView.setCompoundDrawablesRelativeWithIntrinsicBounds(
    187                     drawableStart, null, null, null);
    188         }
    189 
    190         /** A ViewHolder for {@link SeriesRecordingHeaderRow}. */
    191         public static class SeriesHeaderRowViewHolder extends SchedulesHeaderRowViewHolder {
    192             private final TextView mSeriesSettingsButton;
    193             private final TextView mToggleStartStopButton;
    194             private final boolean mLtr;
    195 
    196             private final View mSelector;
    197 
    198             private View mLastFocusedView;
    199 
    200             public SeriesHeaderRowViewHolder(Context context, ViewGroup parent) {
    201                 super(context, parent);
    202                 mLtr =
    203                         context.getResources().getConfiguration().getLayoutDirection()
    204                                 == View.LAYOUT_DIRECTION_LTR;
    205                 view.findViewById(R.id.button_container).setVisibility(View.VISIBLE);
    206                 mSeriesSettingsButton = (TextView) view.findViewById(R.id.series_settings);
    207                 mToggleStartStopButton =
    208                         (TextView) view.findViewById(R.id.series_toggle_start_stop);
    209                 mSelector = view.findViewById(R.id.selector);
    210                 OnFocusChangeListener onFocusChangeListener =
    211                         new View.OnFocusChangeListener() {
    212                             @Override
    213                             public void onFocusChange(View view, boolean focused) {
    214                                 view.post(
    215                                         new Runnable() {
    216                                             @Override
    217                                             public void run() {
    218                                                 updateSelector(view);
    219                                             }
    220                                         });
    221                             }
    222                         };
    223                 mSeriesSettingsButton.setOnFocusChangeListener(onFocusChangeListener);
    224                 mToggleStartStopButton.setOnFocusChangeListener(onFocusChangeListener);
    225             }
    226 
    227             private void updateSelector(View focusedView) {
    228                 int animationDuration =
    229                         mSelector
    230                                 .getContext()
    231                                 .getResources()
    232                                 .getInteger(android.R.integer.config_shortAnimTime);
    233                 DecelerateInterpolator interpolator = new DecelerateInterpolator();
    234 
    235                 if (focusedView.hasFocus()) {
    236                     ViewGroup.LayoutParams lp = mSelector.getLayoutParams();
    237                     final int targetWidth = focusedView.getWidth();
    238                     float targetTranslationX;
    239                     if (mLtr) {
    240                         targetTranslationX = focusedView.getLeft() - mSelector.getLeft();
    241                     } else {
    242                         targetTranslationX = focusedView.getRight() - mSelector.getRight();
    243                     }
    244 
    245                     // if the selector is invisible, set the width and translation X directly -
    246                     // don't animate.
    247                     if (mSelector.getAlpha() == 0) {
    248                         mSelector.setTranslationX(targetTranslationX);
    249                         lp.width = targetWidth;
    250                         mSelector.requestLayout();
    251                     }
    252 
    253                     // animate the selector in and to the proper width and translation X.
    254                     final float deltaWidth = lp.width - targetWidth;
    255                     mSelector.animate().cancel();
    256                     mSelector
    257                             .animate()
    258                             .translationX(targetTranslationX)
    259                             .alpha(1f)
    260                             .setUpdateListener(
    261                                     new ValueAnimator.AnimatorUpdateListener() {
    262                                         @Override
    263                                         public void onAnimationUpdate(ValueAnimator animation) {
    264                                             // Set width to the proper width for this animation
    265                                             // step.
    266                                             lp.width =
    267                                                     targetWidth
    268                                                             + Math.round(
    269                                                                     deltaWidth
    270                                                                             * (1f
    271                                                                                     - animation
    272                                                                                             .getAnimatedFraction()));
    273                                             mSelector.requestLayout();
    274                                         }
    275                                     })
    276                             .setDuration(animationDuration)
    277                             .setInterpolator(interpolator)
    278                             .start();
    279                     mLastFocusedView = focusedView;
    280                 } else if (mLastFocusedView == focusedView) {
    281                     mSelector.animate().setUpdateListener(null).cancel();
    282                     mSelector
    283                             .animate()
    284                             .alpha(0f)
    285                             .setDuration(animationDuration)
    286                             .setInterpolator(interpolator)
    287                             .start();
    288                     mLastFocusedView = null;
    289                 }
    290             }
    291         }
    292     }
    293 }
    294