• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
onActivityCreated(Bundle savedInstanceState)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
onDestroy()92     public void onDestroy() {
93         super.onDestroy();
94         if (null != mBackgroundTimer) {
95             Log.d(TAG, "onDestroy: " + mBackgroundTimer.toString());
96             mBackgroundTimer.cancel();
97         }
98     }
99 
prepareBackgroundManager()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 
setupUIElements()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 
loadVideoData()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 
setupEventListeners()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
onCreateLoader(int arg0, Bundle arg1)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
onLoadFinished(Loader<HashMap<String, List<Movie>>> arg0, HashMap<String, List<Movie>> data)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
onLoaderReset(Loader<HashMap<String, List<Movie>>> arg0)191     public void onLoaderReset(Loader<HashMap<String, List<Movie>>> arg0) {
192         mRowsAdapter.clear();
193     }
194 
setDefaultBackground(Drawable background)195     protected void setDefaultBackground(Drawable background) {
196         mDefaultBackground = background;
197     }
198 
setDefaultBackground(int resourceId)199     protected void setDefaultBackground(int resourceId) {
200         mDefaultBackground = getResources().getDrawable(resourceId);
201     }
202 
updateBackground(String uri)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 
updateBackground(Drawable drawable)221     protected void updateBackground(Drawable drawable) {
222         BackgroundManager.getInstance(getActivity()).setDrawable(drawable);
223     }
224 
clearBackground()225     protected void clearBackground() {
226         BackgroundManager.getInstance(getActivity()).setDrawable(mDefaultBackground);
227     }
228 
startBackgroundTimer()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 
updateRecommendations()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
run()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
onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row)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
onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row)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