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 android.content.Context; 17 import android.os.Build; 18 import android.os.Bundle; 19 import android.os.Handler; 20 import android.support.v17.leanback.widget.Action; 21 import android.support.v17.leanback.widget.ArrayObjectAdapter; 22 import android.support.v17.leanback.widget.ClassPresenterSelector; 23 import android.support.v17.leanback.widget.HeaderItem; 24 import android.support.v17.leanback.widget.ListRow; 25 import android.support.v17.leanback.widget.ListRowPresenter; 26 import android.support.v17.leanback.widget.OnItemViewClickedListener; 27 import android.support.v17.leanback.widget.OnItemViewSelectedListener; 28 import android.support.v17.leanback.widget.PlaybackControlsRow; 29 import android.support.v17.leanback.widget.PlaybackControlsRowPresenter; 30 import android.support.v17.leanback.widget.Presenter; 31 import android.support.v17.leanback.widget.Row; 32 import android.support.v17.leanback.widget.RowPresenter; 33 import android.support.v17.leanback.widget.SparseArrayObjectAdapter; 34 import android.util.Log; 35 36 public class PlaybackOverlayFragment 37 extends android.support.v17.leanback.app.PlaybackOverlayFragment 38 implements PlaybackOverlayActivity.PictureInPictureListener { 39 private static final String TAG = "leanback.PlaybackControlsFragment"; 40 41 /** 42 * Change this to choose a different overlay background. 43 */ 44 private static final int BACKGROUND_TYPE = PlaybackOverlayFragment.BG_LIGHT; 45 46 /** 47 * Change the number of related content rows. 48 */ 49 private static final int RELATED_CONTENT_ROWS = 3; 50 51 /** 52 * Change this to select hidden 53 */ 54 private static final boolean SECONDARY_HIDDEN = false; 55 56 private static final int ROW_CONTROLS = 0; 57 58 private PlaybackControlHelper mGlue; 59 final Handler mHandler = new Handler(); 60 61 // Artificial delay to simulate a media being prepared. The onRowChanged callback should be 62 // called and the playback row UI should be updated after this delay. 63 private static final int MEDIA_PREPARATION_DELAY = 500; 64 65 private OnItemViewClickedListener mOnItemViewClickedListener = new OnItemViewClickedListener() { 66 @Override 67 public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, 68 RowPresenter.ViewHolder rowViewHolder, Row row) { 69 Log.i(TAG, "onItemClicked: " + item + " row " + row); 70 if (item instanceof Action) { 71 mGlue.onActionClicked((Action) item); 72 } 73 } 74 }; 75 76 private OnItemViewSelectedListener mOnItemViewSelectedListener = 77 new OnItemViewSelectedListener() { 78 @Override 79 public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, 80 RowPresenter.ViewHolder rowViewHolder, Row row) { 81 Log.i(TAG, "onItemSelected: " + item + " row " + row); 82 } 83 }; 84 85 @Override getAdapter()86 public SparseArrayObjectAdapter getAdapter() { 87 return (SparseArrayObjectAdapter) super.getAdapter(); 88 } 89 90 @Override onCreate(Bundle savedInstanceState)91 public void onCreate(Bundle savedInstanceState) { 92 Log.i(TAG, "onCreate"); 93 super.onCreate(savedInstanceState); 94 95 setBackgroundType(BACKGROUND_TYPE); 96 setOnItemViewSelectedListener(mOnItemViewSelectedListener); 97 98 createComponents(getActivity()); 99 } 100 createComponents(Context context)101 private void createComponents(Context context) { 102 mGlue = new PlaybackControlHelper(context, this) { 103 @Override 104 public int getUpdatePeriod() { 105 long totalTime = getControlsRow().getDuration(); 106 if (getView() == null || getView().getWidth() == 0 || totalTime <= 0) { 107 return 1000; 108 } 109 return 16; 110 } 111 112 @Override 113 protected void onRowChanged(PlaybackControlsRow row) { 114 if (getAdapter() == null) { 115 return; 116 } 117 int index = getAdapter().indexOf(row); 118 if (index >= 0) { 119 getAdapter().notifyArrayItemRangeChanged(index, 1); 120 } 121 } 122 123 @Override 124 public void onActionClicked(Action action) { 125 if (action.getId() == R.id.lb_control_picture_in_picture) { 126 if (Build.VERSION.SDK_INT >= 24) { 127 getActivity().enterPictureInPictureMode(); 128 } 129 return; 130 } 131 super.onActionClicked(action); 132 } 133 }; 134 135 mGlue.setInitialized(false); 136 mHandler.postDelayed(new Runnable() { 137 @Override 138 public void run() { 139 mGlue.setInitialized(true); 140 } 141 }, MEDIA_PREPARATION_DELAY); 142 mGlue.setOnItemViewClickedListener(mOnItemViewClickedListener); 143 144 PlaybackControlsRowPresenter playbackControlsRowPresenter = 145 mGlue.createControlsRowAndPresenter(); 146 playbackControlsRowPresenter.setSecondaryActionsHidden(SECONDARY_HIDDEN); 147 ClassPresenterSelector selector = new ClassPresenterSelector(); 148 selector.addClassPresenter(ListRow.class, new ListRowPresenter()); 149 selector.addClassPresenter(PlaybackControlsRow.class, playbackControlsRowPresenter); 150 151 setAdapter(new SparseArrayObjectAdapter(selector)); 152 153 // Add the controls row 154 getAdapter().set(ROW_CONTROLS, mGlue.getControlsRow()); 155 156 // Add related content rows 157 for (int i = 0; i < RELATED_CONTENT_ROWS; ++i) { 158 ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new StringPresenter()); 159 listRowAdapter.add("Some related content"); 160 listRowAdapter.add("Other related content"); 161 HeaderItem header = new HeaderItem(i, "Row " + i); 162 getAdapter().set(ROW_CONTROLS + 1 + i, new ListRow(header, listRowAdapter)); 163 } 164 165 } 166 167 @Override onStart()168 public void onStart() { 169 super.onStart(); 170 mGlue.setFadingEnabled(true); 171 mGlue.enableProgressUpdating(true); 172 ((PlaybackOverlayActivity) getActivity()).registerPictureInPictureListener(this); 173 } 174 175 @Override onStop()176 public void onStop() { 177 mGlue.enableProgressUpdating(false); 178 ((PlaybackOverlayActivity) getActivity()).unregisterPictureInPictureListener(this); 179 super.onStop(); 180 } 181 182 @Override onPictureInPictureModeChanged(boolean isInPictureInPictureMode)183 public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) { 184 if (isInPictureInPictureMode) { 185 // Hide the controls in picture-in-picture mode. 186 setFadingEnabled(true); 187 fadeOut(); 188 } else { 189 setFadingEnabled(mGlue.isPlaying()); 190 } 191 } 192 } 193