Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2014 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 com.example.android.tvleanback.ui;
     16 
     17 import android.app.LoaderManager;
     18 import android.content.Intent;
     19 import android.content.Loader;
     20 import android.graphics.drawable.Drawable;
     21 import android.os.Bundle;
     22 import android.os.Handler;
     23 import android.support.v17.leanback.app.BackgroundManager;
     24 import android.support.v17.leanback.app.BrowseFragment;
     25 import android.support.v17.leanback.widget.ArrayObjectAdapter;
     26 import android.support.v17.leanback.widget.HeaderItem;
     27 import android.support.v17.leanback.widget.ImageCardView;
     28 import android.support.v17.leanback.widget.ListRow;
     29 import android.support.v17.leanback.widget.ListRowPresenter;
     30 import android.support.v17.leanback.widget.OnItemViewClickedListener;
     31 import android.support.v17.leanback.widget.OnItemViewSelectedListener;
     32 import android.support.v17.leanback.widget.Presenter;
     33 import android.support.v17.leanback.widget.Row;
     34 import android.support.v17.leanback.widget.RowPresenter;
     35 import android.support.v4.app.ActivityOptionsCompat;
     36 import android.util.DisplayMetrics;
     37 import android.util.Log;
     38 import android.view.View;
     39 import android.widget.Toast;
     40 
     41 
     42 import com.bumptech.glide.Glide;
     43 import com.bumptech.glide.load.resource.drawable.GlideDrawable;
     44 import com.bumptech.glide.request.animation.GlideAnimation;
     45 import com.bumptech.glide.request.target.SimpleTarget;
     46 
     47 import com.example.android.tvleanback.R;
     48 import com.example.android.tvleanback.data.VideoItemLoader;
     49 import com.example.android.tvleanback.data.VideoProvider;
     50 import com.example.android.tvleanback.model.Movie;
     51 import com.example.android.tvleanback.presenter.CardPresenter;
     52 import com.example.android.tvleanback.presenter.GridItemPresenter;
     53 import com.example.android.tvleanback.recommendation.UpdateRecommendationsService;
     54 
     55 import java.net.URI;
     56 import java.util.HashMap;
     57 import java.util.List;
     58 import java.util.Map;
     59 import java.util.Timer;
     60 import java.util.TimerTask;
     61 
     62 /*
     63  * Main class to show BrowseFragment with header and rows of videos
     64  */
     65 public class MainFragment extends BrowseFragment implements
     66         LoaderManager.LoaderCallbacks<HashMap<String, List<Movie>>> {
     67     private static final String TAG = "MainFragment";
     68 
     69     private static int BACKGROUND_UPDATE_DELAY = 300;
     70     private static String mVideosUrl;
     71     private final Handler mHandler = new Handler();
     72     private ArrayObjectAdapter mRowsAdapter;
     73     private Drawable mDefaultBackground;
     74     private DisplayMetrics mMetrics;
     75     private Timer mBackgroundTimer;
     76     private URI mBackgroundURI;
     77     private BackgroundManager mBackgroundManager;
     78 
     79     @Override
     80     public void onActivityCreated(Bundle savedInstanceState) {
     81         Log.d(TAG, "onCreate");
     82         super.onActivityCreated(savedInstanceState);
     83 
     84         loadVideoData();
     85 
     86         prepareBackgroundManager();
     87         setupUIElements();
     88         setupEventListeners();
     89     }
     90 
     91     @Override
     92     public void onDestroy() {
     93         super.onDestroy();
     94         if (null != mBackgroundTimer) {
     95             Log.d(TAG, "onDestroy: " + mBackgroundTimer.toString());
     96             mBackgroundTimer.cancel();
     97         }
     98     }
     99 
    100     private void prepareBackgroundManager() {
    101         mBackgroundManager = BackgroundManager.getInstance(getActivity());
    102         mBackgroundManager.attach(getActivity().getWindow());
    103         mDefaultBackground = getResources().getDrawable(R.drawable.default_background);
    104         mMetrics = new DisplayMetrics();
    105         getActivity().getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
    106     }
    107 
    108     private void setupUIElements() {
    109         setBadgeDrawable(getActivity().getResources().getDrawable(R.drawable.videos_by_google_banner));
    110         setTitle(getString(R.string.browse_title)); // Badge, when set, takes precedent over title
    111         setHeadersState(HEADERS_ENABLED);
    112         setHeadersTransitionOnBackEnabled(true);
    113         // set fastLane (or headers) background color
    114         setBrandColor(getResources().getColor(R.color.fastlane_background));
    115         // set search icon color
    116         setSearchAffordanceColor(getResources().getColor(R.color.search_opaque));
    117     }
    118 
    119     private void loadVideoData() {
    120         VideoProvider.setContext(getActivity());
    121         mVideosUrl = getActivity().getResources().getString(R.string.catalog_url);
    122         getLoaderManager().initLoader(0, null, this);
    123     }
    124 
    125     private void setupEventListeners() {
    126         setOnSearchClickedListener(new View.OnClickListener() {
    127 
    128             @Override
    129             public void onClick(View view) {
    130                 Intent intent = new Intent(getActivity(), SearchActivity.class);
    131                 startActivity(intent);
    132             }
    133         });
    134 
    135         setOnItemViewClickedListener(new ItemViewClickedListener());
    136         setOnItemViewSelectedListener(new ItemViewSelectedListener());
    137     }
    138 
    139     /*
    140      * (non-Javadoc)
    141      * @see android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader(int,
    142      * android.os.Bundle)
    143      */
    144     @Override
    145     public Loader<HashMap<String, List<Movie>>> onCreateLoader(int arg0, Bundle arg1) {
    146         Log.d(TAG, "VideoItemLoader created ");
    147         return new VideoItemLoader(getActivity(), mVideosUrl);
    148     }
    149 
    150     /*
    151      * (non-Javadoc)
    152      * @see android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished(android
    153      * .support.v4.content.Loader, java.lang.Object)
    154      */
    155     @Override
    156     public void onLoadFinished(Loader<HashMap<String, List<Movie>>> arg0,
    157                                HashMap<String, List<Movie>> data) {
    158 
    159         mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
    160         CardPresenter cardPresenter = new CardPresenter();
    161 
    162         int i = 0;
    163 
    164         for (Map.Entry<String, List<Movie>> entry : data.entrySet()) {
    165             ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
    166             List<Movie> list = entry.getValue();
    167 
    168             for (int j = 0; j < list.size(); j++) {
    169                 listRowAdapter.add(list.get(j));
    170             }
    171             HeaderItem header = new HeaderItem(i, entry.getKey());
    172             i++;
    173             mRowsAdapter.add(new ListRow(header, listRowAdapter));
    174         }
    175 
    176         HeaderItem gridHeader = new HeaderItem(i, getString(R.string.more_samples));
    177 
    178         GridItemPresenter gridPresenter = new GridItemPresenter(this);
    179         ArrayObjectAdapter gridRowAdapter = new ArrayObjectAdapter(gridPresenter);
    180         gridRowAdapter.add(getString(R.string.grid_view));
    181         gridRowAdapter.add(getString(R.string.error_fragment));
    182         gridRowAdapter.add(getString(R.string.personal_settings));
    183         mRowsAdapter.add(new ListRow(gridHeader, gridRowAdapter));
    184 
    185         setAdapter(mRowsAdapter);
    186 
    187         updateRecommendations();
    188     }
    189 
    190     @Override
    191     public void onLoaderReset(Loader<HashMap<String, List<Movie>>> arg0) {
    192         mRowsAdapter.clear();
    193     }
    194 
    195     protected void setDefaultBackground(Drawable background) {
    196         mDefaultBackground = background;
    197     }
    198 
    199     protected void setDefaultBackground(int resourceId) {
    200         mDefaultBackground = getResources().getDrawable(resourceId);
    201     }
    202 
    203     protected void updateBackground(String uri) {
    204         int width = mMetrics.widthPixels;
    205         int height = mMetrics.heightPixels;
    206         Glide.with(getActivity())
    207                 .load(uri)
    208                 .centerCrop()
    209                 .error(mDefaultBackground)
    210                 .into(new SimpleTarget<GlideDrawable>(width, height) {
    211                     @Override
    212                     public void onResourceReady(GlideDrawable resource,
    213                                                 GlideAnimation<? super GlideDrawable>
    214                                                         glideAnimation) {
    215                         mBackgroundManager.setDrawable(resource);
    216                     }
    217                 });
    218         mBackgroundTimer.cancel();
    219     }
    220 
    221     protected void updateBackground(Drawable drawable) {
    222         BackgroundManager.getInstance(getActivity()).setDrawable(drawable);
    223     }
    224 
    225     protected void clearBackground() {
    226         BackgroundManager.getInstance(getActivity()).setDrawable(mDefaultBackground);
    227     }
    228 
    229     private void startBackgroundTimer() {
    230         if (null != mBackgroundTimer) {
    231             mBackgroundTimer.cancel();
    232         }
    233         mBackgroundTimer = new Timer();
    234         mBackgroundTimer.schedule(new UpdateBackgroundTask(), BACKGROUND_UPDATE_DELAY);
    235     }
    236 
    237     private void updateRecommendations() {
    238         Intent recommendationIntent = new Intent(getActivity(), UpdateRecommendationsService.class);
    239         getActivity().startService(recommendationIntent);
    240     }
    241 
    242     private class UpdateBackgroundTask extends TimerTask {
    243 
    244         @Override
    245         public void run() {
    246             mHandler.post(new Runnable() {
    247                 @Override
    248                 public void run() {
    249                     if (mBackgroundURI != null) {
    250                         updateBackground(mBackgroundURI.toString());
    251                     }
    252                 }
    253             });
    254         }
    255     }
    256 
    257     private final class ItemViewClickedListener implements OnItemViewClickedListener {
    258         @Override
    259         public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
    260                                   RowPresenter.ViewHolder rowViewHolder, Row row) {
    261 
    262             if (item instanceof Movie) {
    263                 Movie movie = (Movie) item;
    264                 Log.d(TAG, "Movie: " + movie.toString());
    265                 Intent intent = new Intent(getActivity(), MovieDetailsActivity.class);
    266                 intent.putExtra(MovieDetailsActivity.MOVIE, movie);
    267 
    268                 Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
    269                         getActivity(),
    270                         ((ImageCardView) itemViewHolder.view).getMainImageView(),
    271                         MovieDetailsActivity.SHARED_ELEMENT_NAME).toBundle();
    272                 getActivity().startActivity(intent, bundle);
    273             } else if (item instanceof String) {
    274                 if (((String) item).indexOf(getString(R.string.grid_view)) >= 0) {
    275                     Intent intent = new Intent(getActivity(), VerticalGridActivity.class);
    276                     startActivity(intent);
    277                 } else if (((String) item).indexOf(getString(R.string.error_fragment)) >= 0) {
    278                     Intent intent = new Intent(getActivity(), BrowseErrorActivity.class);
    279                     startActivity(intent);
    280                 } else {
    281                     Toast.makeText(getActivity(), ((String) item), Toast.LENGTH_SHORT)
    282                             .show();
    283                 }
    284             }
    285         }
    286     }
    287 
    288 
    289     private final class ItemViewSelectedListener implements OnItemViewSelectedListener {
    290         @Override
    291         public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
    292                                    RowPresenter.ViewHolder rowViewHolder, Row row) {
    293             if (item instanceof Movie) {
    294                 mBackgroundURI = ((Movie) item).getBackgroundImageURI();
    295                 startBackgroundTimer();
    296             }
    297 
    298         }
    299     }
    300 }
    301