Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
      5  * in compliance with the License. You may obtain a copy of the License at
      6  *
      7  * http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software distributed under the License
     10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
     11  * or implied. See the License for the specific language governing permissions and limitations under
     12  * the License.
     13  */
     14 
     15 package android.leanbackjank.app.ui;
     16 
     17 import android.content.Intent;
     18 import android.content.res.Resources;
     19 import android.content.res.Resources.Theme;
     20 import android.leanbackjank.app.IntentKeys;
     21 import android.leanbackjank.app.R;
     22 import android.leanbackjank.app.data.VideoProvider;
     23 import android.leanbackjank.app.model.Movie;
     24 import android.leanbackjank.app.presenter.CardPresenter;
     25 import android.leanbackjank.app.presenter.IconHeaderItemPresenter;
     26 import android.os.Bundle;
     27 import android.os.Handler;
     28 import androidx.leanback.app.BackgroundManager;
     29 import androidx.leanback.app.BrowseFragment;
     30 import androidx.leanback.widget.ArrayObjectAdapter;
     31 import androidx.leanback.widget.HeaderItem;
     32 import androidx.leanback.widget.ListRow;
     33 import androidx.leanback.widget.ListRowPresenter;
     34 import androidx.leanback.widget.Presenter;
     35 import androidx.leanback.widget.PresenterSelector;
     36 import androidx.leanback.widget.ShadowOverlayHelper;
     37 import android.util.DisplayMetrics;
     38 import android.view.View;
     39 
     40 import java.util.HashMap;
     41 import java.util.List;
     42 import java.util.Map;
     43 import java.util.Timer;
     44 import java.util.TimerTask;
     45 
     46 class ScrollPatternGenerator {
     47     private int currentRow;
     48     private int topRow;
     49     private int bottomRow;
     50     private enum ScrollDirection {DOWN, UP};
     51     private ScrollDirection direction;
     52 
     53     public ScrollPatternGenerator(int topRow, int bottomRow) {
     54         this.topRow = topRow;
     55         this.bottomRow = bottomRow;
     56         assert(topRow < bottomRow);
     57         direction = ScrollDirection.DOWN;
     58         currentRow = topRow;
     59     }
     60 
     61     public int next() {
     62         if (currentRow == bottomRow) {
     63             direction = ScrollDirection.UP;
     64         } else if (currentRow == topRow) {
     65             direction = ScrollDirection.DOWN;
     66         }
     67         if (direction == ScrollDirection.DOWN) {
     68             currentRow++;
     69         } else {
     70             currentRow--;
     71         }
     72         return currentRow;
     73     }
     74 }
     75 
     76 /**
     77  * Main class to show BrowseFragment with header and rows of videos
     78  */
     79 public class MainFragment extends BrowseFragment {
     80     private static final int NUM_ROWS = 20;
     81 
     82     // Minimum number of rows that should show above / below the cursor by auto scroll.
     83     // This is intended to avoid that the work load fluctuates largely when # of cards in the
     84     // display lowers when the cursor is positioned near the top or bottom of the list.
     85     private static final int MARGIN_ROWS = 4;
     86 
     87     private final Handler mHandler = new Handler();
     88     private Timer mAutoScrollTimer;
     89     private int mAutoScrollCount;
     90 
     91     private ArrayObjectAdapter mRowsAdapter;
     92     private DisplayMetrics mMetrics;
     93     private BackgroundManager mBackgroundManager;
     94     private ScrollPatternGenerator scrollPatternGenerator;
     95 
     96     @Override
     97     public void onActivityCreated(Bundle savedInstanceState) {
     98         super.onActivityCreated(savedInstanceState);
     99 
    100         buildRowAdapterItems(VideoProvider.buildMedia(NUM_ROWS));
    101         prepareBackgroundManager();
    102         setupUIElements();
    103         setupEventListeners();
    104         Intent intent = getActivity().getIntent();
    105         if (intent.getExtras() != null) {
    106             int initialDelay = intent.getExtras().getInt(IntentKeys.SCROLL_DELAY);
    107             int scrollCount = intent.getExtras().getInt(IntentKeys.SCROLL_COUNT);
    108             int scrollInterval = intent.getExtras().getInt(IntentKeys.SCROLL_INTERVAL);
    109             if (scrollInterval != 0 && scrollCount != 0) {
    110                 startAutoScrollTimer(initialDelay, scrollInterval, scrollCount);
    111             }
    112             scrollPatternGenerator =
    113                     new ScrollPatternGenerator(MARGIN_ROWS, NUM_ROWS - 1 - MARGIN_ROWS);
    114         }
    115     }
    116 
    117     @Override
    118     public void onDestroy() {
    119         if (null != mAutoScrollTimer) {
    120             mAutoScrollTimer.cancel();
    121             mAutoScrollTimer = null;
    122         }
    123         super.onDestroy();
    124     }
    125 
    126     @Override
    127     public void onStop() {
    128         mBackgroundManager.release();
    129         super.onStop();
    130     }
    131 
    132     private void prepareBackgroundManager() {
    133         mBackgroundManager = BackgroundManager.getInstance(getActivity());
    134         mBackgroundManager.attach(getActivity().getWindow());
    135         mBackgroundManager.setDrawable(getActivity().getResources().getDrawable(
    136                 R.drawable.default_background, getContext().getTheme()));
    137         mMetrics = new DisplayMetrics();
    138         getActivity().getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
    139     }
    140 
    141     private void setupUIElements() {
    142         setBadgeDrawable(getActivity().getResources().getDrawable(
    143                 R.drawable.videos_by_google_banner, getContext().getTheme()));
    144         setTitle(getString(R.string.browse_title));
    145         setHeadersState(HEADERS_ENABLED);
    146         setHeadersTransitionOnBackEnabled(true);
    147 
    148         Theme theme = getContext().getTheme();
    149         setBrandColor(getResources().getColor(R.color.fastlane_background, theme));
    150 
    151         setSearchAffordanceColor(getResources().getColor(R.color.search_opaque, theme));
    152 
    153         setHeaderPresenterSelector(new PresenterSelector() {
    154             @Override
    155             public Presenter getPresenter(Object o) {
    156                 return new IconHeaderItemPresenter();
    157             }
    158         });
    159     }
    160 
    161     private void setupEventListeners() {
    162         // Add lister to show the search button.
    163         setOnSearchClickedListener(new View.OnClickListener() {
    164             @Override
    165             public void onClick(View view) {
    166             }
    167         });
    168     }
    169 
    170     public void buildRowAdapterItems(HashMap<String, List<Movie>> data) {
    171         ListRowPresenter listRowPresenter = new ListRowPresenter() {
    172             @Override
    173             protected ShadowOverlayHelper.Options createShadowOverlayOptions() {
    174                 Resources res = getResources();
    175                 ShadowOverlayHelper.Options options = new ShadowOverlayHelper.Options();
    176                 options.dynamicShadowZ(res.getDimension(R.dimen.shadow_unfocused_z),
    177                         res.getDimension(R.dimen.shadow_focused_z));
    178                 return options;
    179             }
    180         };
    181         mRowsAdapter = new ArrayObjectAdapter(listRowPresenter);
    182         CardPresenter cardPresenter = new CardPresenter();
    183 
    184         int i = 0;
    185 
    186         for (Map.Entry<String, List<Movie>> entry : data.entrySet()) {
    187             ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
    188             List<Movie> list = entry.getValue();
    189 
    190             for (int j = 0; j < list.size(); j++) {
    191                 listRowAdapter.add(list.get(j));
    192             }
    193             HeaderItem header = new HeaderItem(i, entry.getKey());
    194             i++;
    195             mRowsAdapter.add(new ListRow(header, listRowAdapter));
    196         }
    197 
    198         setAdapter(mRowsAdapter);
    199     }
    200 
    201     private class UpdateAutoScrollTask extends TimerTask {
    202         @Override
    203         public void run() {
    204             mHandler.post(new Runnable() {
    205                 @Override
    206                 public void run() {
    207                     if (mAutoScrollCount == 0) {
    208                       mAutoScrollTimer.cancel();
    209                       return;
    210                     }
    211                     setSelectedPosition(scrollPatternGenerator.next());
    212                     mAutoScrollCount--;
    213                 }
    214             });
    215         }
    216     }
    217 
    218     private void startAutoScrollTimer(int initialDelay, int interval, int count) {
    219         if (null != mAutoScrollTimer) {
    220             mAutoScrollTimer.cancel();
    221         }
    222         mAutoScrollCount = count;
    223         mAutoScrollTimer = new Timer();
    224         mAutoScrollTimer.schedule(new UpdateAutoScrollTask(), initialDelay, interval);
    225     }
    226 
    227     public void selectRow(int row) {
    228         setSelectedPosition(row);
    229     }
    230 }
    231