• 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 package com.example.android.leanback;
15 
16 import java.util.ArrayList;
17 
18 import android.content.Context;
19 import android.content.res.Resources;
20 import android.graphics.drawable.Drawable;
21 import android.os.Bundle;
22 import android.os.Handler;
23 import android.support.v17.leanback.widget.Action;
24 import android.support.v17.leanback.widget.ArrayObjectAdapter;
25 import android.support.v17.leanback.widget.ClassPresenterSelector;
26 import android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter;
27 import android.support.v17.leanback.widget.PlaybackControlsRow;
28 import android.support.v17.leanback.widget.PlaybackControlsRow.PlayPauseAction;
29 import android.support.v17.leanback.widget.PlaybackControlsRow.RepeatAction;
30 import android.support.v17.leanback.widget.PlaybackControlsRow.ThumbsUpAction;
31 import android.support.v17.leanback.widget.PlaybackControlsRow.ThumbsDownAction;
32 import android.support.v17.leanback.widget.PlaybackControlsRow.ShuffleAction;
33 import android.support.v17.leanback.widget.PlaybackControlsRow.SkipNextAction;
34 import android.support.v17.leanback.widget.PlaybackControlsRow.SkipPreviousAction;
35 import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
36 import android.support.v17.leanback.widget.HeaderItem;
37 import android.support.v17.leanback.widget.VerticalGridView;
38 import android.support.v17.leanback.widget.Row;
39 import android.support.v17.leanback.widget.ListRow;
40 import android.support.v17.leanback.widget.Presenter;
41 import android.support.v17.leanback.widget.RowPresenter;
42 import android.support.v17.leanback.widget.ListRowPresenter;
43 import android.support.v17.leanback.widget.OnActionClickedListener;
44 import android.support.v17.leanback.widget.OnItemViewSelectedListener;
45 import android.support.v17.leanback.widget.OnItemViewClickedListener;
46 import android.support.v17.leanback.widget.ControlButtonPresenterSelector;
47 import android.util.Log;
48 import android.widget.Toast;
49 
50 public class PlaybackOverlayFragment extends android.support.v17.leanback.app.PlaybackOverlayFragment {
51     private static final String TAG = "leanback.PlaybackControlsFragment";
52 
53     private static final boolean SHOW_DETAIL = true;
54     private static final boolean HIDE_MORE_ACTIONS = false;
55     private static final int PRIMARY_CONTROLS = 5;
56     private static final boolean SHOW_IMAGE = PRIMARY_CONTROLS <= 5;
57     private static final int BACKGROUND_TYPE = PlaybackOverlayFragment.BG_LIGHT;
58     private static final int MORE_ROWS = 3;
59 
60     private ArrayObjectAdapter mRowsAdapter;
61     private ArrayObjectAdapter mPrimaryActionsAdapter;
62     private ArrayObjectAdapter mSecondaryActionsAdapter;
63     private PlayPauseAction mPlayPauseAction;
64     private RepeatAction mRepeatAction;
65     private ThumbsUpAction mThumbsUpAction;
66     private ThumbsDownAction mThumbsDownAction;
67     private ShuffleAction mShuffleAction;
68     private SkipNextAction mSkipNextAction;
69     private SkipPreviousAction mSkipPreviousAction;
70     private PlaybackControlsRow mPlaybackControlsRow;
71     private ArrayList<MediaItem> mItems = new ArrayList<MediaItem>();
72     private int mCurrentItem;
73     private Handler mHandler;
74     private Runnable mRunnable;
75 
76     @Override
onCreate(Bundle savedInstanceState)77     public void onCreate(Bundle savedInstanceState) {
78         Log.i(TAG, "onCreate");
79         super.onCreate(savedInstanceState);
80 
81         mHandler = new Handler();
82 
83         setBackgroundType(BACKGROUND_TYPE);
84         setFadingEnabled(false);
85 
86         setupRows();
87 
88         setOnItemViewSelectedListener(new OnItemViewSelectedListener() {
89             @Override
90             public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
91                     RowPresenter.ViewHolder rowViewHolder, Row row) {
92                 Log.i(TAG, "onItemSelected: " + item + " row " + row);
93             }
94         });
95         setOnItemViewClickedListener(new OnItemViewClickedListener() {
96             @Override
97             public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
98                     RowPresenter.ViewHolder rowViewHolder, Row row) {
99                 Log.i(TAG, "onItemClicked: " + item + " row " + row);
100             }
101         });
102     }
103 
104 
setupRows()105     private void setupRows() {
106         ClassPresenterSelector ps = new ClassPresenterSelector();
107 
108         PlaybackControlsRowPresenter playbackControlsRowPresenter;
109         if (SHOW_DETAIL) {
110             playbackControlsRowPresenter = new PlaybackControlsRowPresenter(
111                     new DescriptionPresenter());
112         } else {
113             playbackControlsRowPresenter = new PlaybackControlsRowPresenter();
114         }
115         playbackControlsRowPresenter.setOnActionClickedListener(new OnActionClickedListener() {
116             public void onActionClicked(Action action) {
117                 if (action.getId() == mPlayPauseAction.getId()) {
118                     if (mPlayPauseAction.getIndex() == PlayPauseAction.PLAY) {
119                         startProgressAutomation();
120                         setFadingEnabled(true);
121                     } else {
122                         stopProgressAutomation();
123                         setFadingEnabled(false);
124                     }
125                 } else if (action.getId() == mSkipNextAction.getId()) {
126                     next();
127                 } else if (action.getId() == mSkipPreviousAction.getId()) {
128                     Toast.makeText(getActivity(), "TODO", Toast.LENGTH_SHORT).show();
129                 }
130                 if (action instanceof PlaybackControlsRow.MultiAction) {
131                     ((PlaybackControlsRow.MultiAction) action).nextIndex();
132                     notifyChanged(action);
133                 }
134             }
135         });
136         playbackControlsRowPresenter.setSecondaryActionsHidden(HIDE_MORE_ACTIONS);
137 
138         ps.addClassPresenter(PlaybackControlsRow.class, playbackControlsRowPresenter);
139         ps.addClassPresenter(ListRow.class, new ListRowPresenter());
140         mRowsAdapter = new ArrayObjectAdapter(ps);
141 
142         addPlaybackControlsRow();
143         addOtherRows();
144 
145         setAdapter(mRowsAdapter);
146     }
147 
addPlaybackControlsRow()148     private void addPlaybackControlsRow() {
149         Context context = getActivity();
150 
151         if (SHOW_DETAIL) {
152             mPlaybackControlsRow = new PlaybackControlsRow(new MediaItem());
153         } else {
154             mPlaybackControlsRow = new PlaybackControlsRow();
155         }
156         mRowsAdapter.add(mPlaybackControlsRow);
157 
158         mItems = new ArrayList<MediaItem>();
159         mItems.add(new MediaItem("Awesome Tune", "The More Awesome Band", R.drawable.details_img, 15*1000));
160         mItems.add(new MediaItem("Pretty nice Tune", "The Nice Guys", R.drawable.details_img, 10*1000));
161         mCurrentItem = 1;
162         updatePlaybackRow(mCurrentItem);
163 
164         ControlButtonPresenterSelector presenterSelector = new ControlButtonPresenterSelector();
165         mPrimaryActionsAdapter = new ArrayObjectAdapter(presenterSelector);
166         mSecondaryActionsAdapter = new ArrayObjectAdapter(presenterSelector);
167         mPlaybackControlsRow.setPrimaryActionsAdapter(mPrimaryActionsAdapter);
168         mPlaybackControlsRow.setSecondaryActionsAdapter(mSecondaryActionsAdapter);
169 
170         mPlayPauseAction = new PlayPauseAction(context);
171         mRepeatAction = new RepeatAction(context);
172         mThumbsUpAction = new ThumbsUpAction(context);
173         mThumbsDownAction = new ThumbsDownAction(context);
174         mShuffleAction = new ShuffleAction(context);
175         mSkipNextAction = new PlaybackControlsRow.SkipNextAction(context);
176         mSkipPreviousAction = new PlaybackControlsRow.SkipPreviousAction(context);
177 
178         if (PRIMARY_CONTROLS > 5) {
179             mPrimaryActionsAdapter.add(mThumbsUpAction);
180         } else {
181             mSecondaryActionsAdapter.add(mThumbsUpAction);
182         }
183         mPrimaryActionsAdapter.add(mSkipPreviousAction);
184         if (PRIMARY_CONTROLS > 3) {
185             mPrimaryActionsAdapter.add(new PlaybackControlsRow.RewindAction(context));
186         }
187         mPrimaryActionsAdapter.add(mPlayPauseAction);
188         if (PRIMARY_CONTROLS > 3) {
189             mPrimaryActionsAdapter.add(new PlaybackControlsRow.FastForwardAction(context));
190         }
191         mPrimaryActionsAdapter.add(mSkipNextAction);
192 
193         mSecondaryActionsAdapter.add(mRepeatAction);
194         mSecondaryActionsAdapter.add(mShuffleAction);
195         if (PRIMARY_CONTROLS > 5) {
196             mPrimaryActionsAdapter.add(mThumbsDownAction);
197         } else {
198             mSecondaryActionsAdapter.add(mThumbsDownAction);
199         }
200         mSecondaryActionsAdapter.add(new PlaybackControlsRow.HighQualityAction(context));
201         mSecondaryActionsAdapter.add(new PlaybackControlsRow.ClosedCaptioningAction(context));
202     }
203 
notifyChanged(Action action)204     private void notifyChanged(Action action) {
205         ArrayObjectAdapter adapter = mPrimaryActionsAdapter;
206         if (adapter.indexOf(action) >= 0) {
207             adapter.notifyArrayItemRangeChanged(adapter.indexOf(action), 1);
208             return;
209         }
210         adapter = mSecondaryActionsAdapter;
211         if (adapter.indexOf(action) >= 0) {
212             adapter.notifyArrayItemRangeChanged(adapter.indexOf(action), 1);
213             return;
214         }
215     }
216 
updatePlaybackRow(int index)217     private void updatePlaybackRow(int index) {
218         if (mPlaybackControlsRow.getItem() != null) {
219             MediaItem item = (MediaItem) mPlaybackControlsRow.getItem();
220             item.title = mItems.get(index).title;
221             item.subtitle = mItems.get(index).subtitle;
222         }
223         if (SHOW_IMAGE) {
224             mPlaybackControlsRow.setImageDrawable(getResources().getDrawable(
225                     mItems.get(mCurrentItem).imageResId));
226         }
227         mRowsAdapter.notifyArrayItemRangeChanged(0, 1);
228 
229         mPlaybackControlsRow.setTotalTime(mItems.get(mCurrentItem).durationMs);
230         mPlaybackControlsRow.setCurrentTime(0);
231         mPlaybackControlsRow.setBufferedProgress(75 * 1000);
232     }
233 
addOtherRows()234     private void addOtherRows() {
235         for (int i = 0; i < MORE_ROWS; ++i) {
236             ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new StringPresenter());
237             listRowAdapter.add("Some related content");
238             listRowAdapter.add("Other related content");
239             HeaderItem header = new HeaderItem(i, "Row " + i, null);
240             mRowsAdapter.add(new ListRow(header, listRowAdapter));
241         }
242     }
243 
getUpdatePeriod()244     private int getUpdatePeriod() {
245         if (getView() == null || mPlaybackControlsRow.getTotalTime() <= 0) {
246             return 1000;
247         }
248         return Math.max(16, mPlaybackControlsRow.getTotalTime() / getView().getWidth());
249     }
250 
startProgressAutomation()251     private void startProgressAutomation() {
252         mRunnable = new Runnable() {
253             @Override
254             public void run() {
255                 int updatePeriod = getUpdatePeriod();
256                 int currentTime = mPlaybackControlsRow.getCurrentTime() + updatePeriod;
257                 int totalTime = mPlaybackControlsRow.getTotalTime();
258                 mPlaybackControlsRow.setCurrentTime(currentTime);
259                 if (totalTime > 0 && totalTime <= currentTime) {
260                     next();
261                 }
262                 mHandler.postDelayed(this, updatePeriod);
263             }
264         };
265         mHandler.postDelayed(mRunnable, getUpdatePeriod());
266     }
267 
next()268     private void next() {
269         if (++mCurrentItem >= mItems.size()) {
270             mCurrentItem = 0;
271         }
272         updatePlaybackRow(mCurrentItem);
273     }
274 
stopProgressAutomation()275     private void stopProgressAutomation() {
276         if (mHandler != null && mRunnable != null) {
277             mHandler.removeCallbacks(mRunnable);
278         }
279     }
280 
281     @Override
onStop()282     public void onStop() {
283         stopProgressAutomation();
284         super.onStop();
285     }
286 
287     static class MediaItem {
288         String title;
289         String subtitle;
290         int imageResId;
291         int durationMs;
292 
MediaItem()293         MediaItem() {
294         }
295 
MediaItem(String title, String subtitle, int imageResId, int durationMs)296         MediaItem(String title, String subtitle, int imageResId, int durationMs) {
297             this.title = title;
298             this.subtitle = subtitle;
299             this.imageResId = imageResId;
300             this.durationMs = durationMs;
301         }
302     }
303 
304     static class DescriptionPresenter extends AbstractDetailsDescriptionPresenter {
305         @Override
onBindDescription(ViewHolder vh, Object item)306         protected void onBindDescription(ViewHolder vh, Object item) {
307             vh.getTitle().setText(((MediaItem) item).title);
308             vh.getSubtitle().setText(((MediaItem) item).subtitle);
309         }
310     }
311 }
312