Fix PlaybackOverlayFragment sample not work.
am: ef05d5494f
Change-Id: Ifc4003000f810b1726ae5cffc92d548d13b2f9e4
diff --git a/samples/SupportLeanbackDemos/AndroidManifest.xml b/samples/SupportLeanbackDemos/AndroidManifest.xml
index e1acf45..1dba568 100644
--- a/samples/SupportLeanbackDemos/AndroidManifest.xml
+++ b/samples/SupportLeanbackDemos/AndroidManifest.xml
@@ -59,6 +59,22 @@
android:theme="@style/Theme.Example.Leanback.Rows"
android:exported="true" />
+ <activity android:name="PlaybackActivity"
+ android:configChanges=
+ "screenSize|smallestScreenSize|screenLayout|orientation"
+ android:resizeableActivity="true"
+ android:supportsPictureInPicture="true"
+ android:launchMode="singleTask"
+ android:exported="true" />
+
+ <activity android:name="PlaybackSupportActivity"
+ android:configChanges=
+ "screenSize|smallestScreenSize|screenLayout|orientation"
+ android:resizeableActivity="true"
+ android:supportsPictureInPicture="true"
+ android:launchMode="singleTask"
+ android:exported="true" />
+
<activity android:name="PlaybackOverlayActivity"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation"
diff --git a/samples/SupportLeanbackDemos/generatev4.py b/samples/SupportLeanbackDemos/generatev4.py
index efaf0b4..d4b3f22 100755
--- a/samples/SupportLeanbackDemos/generatev4.py
+++ b/samples/SupportLeanbackDemos/generatev4.py
@@ -300,16 +300,58 @@
file.close()
outfile.close()
+file = open('src/com/example/android/leanback/PlaybackFragment.java', 'r')
+outfile = open('src/com/example/android/leanback/PlaybackSupportFragment.java', 'w')
+write_java_head(outfile, "PlaybackFragment")
+for line in file:
+ line = line.replace('PlaybackFragment', 'PlaybackSupportFragment')
+ line = line.replace('PlaybackActivity', 'PlaybackSupportActivity')
+ outfile.write(line)
+file.close()
+outfile.close()
+
+file = open('src/com/example/android/leanback/PlaybackActivity.java', 'r')
+outfile = open('src/com/example/android/leanback/PlaybackSupportActivity.java', 'w')
+write_java_head(outfile, "PlaybackActivity")
+for line in file:
+ line = line.replace('PlaybackActivity', 'PlaybackSupportActivity')
+ line = line.replace('extends Activity', 'extends FragmentActivity')
+ line = line.replace('R.layout.playback_activity', 'R.layout.playback_activity_support')
+ line = line.replace('android.app.Activity', 'android.support.v4.app.FragmentActivity')
+ outfile.write(line)
+file.close()
+outfile.close()
+
+file = open('res/layout/playback_activity.xml', 'r')
+outfile = open('res/layout/playback_activity_support.xml', 'w')
+for line in file:
+ line = replace_xml_head(line, "playback_controls")
+ line = line.replace('com.example.android.leanback.PlaybackFragment', 'com.example.android.leanback.PlaybackSupportFragment')
+ outfile.write(line)
+file.close()
+outfile.close()
+
+
file = open('src/com/example/android/leanback/PlaybackOverlayFragment.java', 'r')
outfile = open('src/com/example/android/leanback/PlaybackOverlaySupportFragment.java', 'w')
write_java_head(outfile, "PlaybackOverlayFragment")
for line in file:
line = line.replace('PlaybackOverlayFragment', 'PlaybackOverlaySupportFragment')
+ line = line.replace('PlaybackControlHelper', 'PlaybackControlSupportHelper')
line = line.replace('PlaybackOverlayActivity', 'PlaybackOverlaySupportActivity')
- line = line.replace('PlaybackFragmentGlueHost', 'PlaybackSupportFragmentGlueHost')
- line = line.replace('VideoFragment', 'VideoSupportFragment')
- line = line.replace('PlaybackFragment', 'PlaybackSupportFragment')
+ outfile.write(line)
+file.close()
+outfile.close()
+
+
+file = open('src/com/example/android/leanback/PlaybackControlHelper.java', 'r')
+outfile = open('src/com/example/android/leanback/PlaybackControlSupportHelper.java', 'w')
+write_java_head(outfile, "PlaybackControlHelper")
+for line in file:
+ line = line.replace('PlaybackControlHelper', 'PlaybackControlSupportHelper')
+ line = line.replace('PlaybackControlGlue', 'PlaybackControlSupportGlue')
+ line = line.replace('PlaybackOverlayFragment', 'PlaybackOverlaySupportFragment')
outfile.write(line)
file.close()
outfile.close()
diff --git a/samples/SupportLeanbackDemos/res/layout/playback_activity.xml b/samples/SupportLeanbackDemos/res/layout/playback_activity.xml
new file mode 100644
index 0000000..91754ff
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/layout/playback_activity.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <fragment
+ android:id="@+id/playback_controls_fragment"
+ android:name="com.example.android.leanback.PlaybackFragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackDemos/res/layout/playback_activity_support.xml b/samples/SupportLeanbackDemos/res/layout/playback_activity_support.xml
new file mode 100644
index 0000000..0f2cbc1
--- /dev/null
+++ b/samples/SupportLeanbackDemos/res/layout/playback_activity_support.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This file is auto-generated from playback_controls.xml. DO NOT MODIFY. -->
+
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <fragment
+ android:id="@+id/playback_controls_fragment"
+ android:name="com.example.android.leanback.PlaybackSupportFragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackDemos/res/values/strings.xml b/samples/SupportLeanbackDemos/res/values/strings.xml
index 6a9b4a3..3774ebf 100644
--- a/samples/SupportLeanbackDemos/res/values/strings.xml
+++ b/samples/SupportLeanbackDemos/res/values/strings.xml
@@ -35,12 +35,16 @@
<string name="search_details_description">Search style DetailsFragment test</string>
<string name="search_details_support">Search Details(support version)</string>
<string name="search_details_support_description">Search style DetailsSupportFragment test</string>
- <string name="playback">Playback</string>
<string name="video_playback">Video Playback</string>
<string name="video_playback_support">Video Playback(support version)</string>
- <string name="playback_description">PlaybackOverlayFragment test</string>
+ <string name="playback">Playback</string>
+ <string name="playback_description">PlaybackFragment test</string>
<string name="playback_support">Playback(support version)</string>
- <string name="playback_support_description">PlaybackOverlaySupportFragment test</string>
+ <string name="playback_support_description">PlaybackSupportFragment test</string>
+ <string name="playbackoverlay">PlaybackOverlay</string>
+ <string name="playbackoverlay_description">PlaybackOverlayFragment test</string>
+ <string name="playbackoverlay_support">PlaybackOverlay(support version)</string>
+ <string name="playbackoverlay_support_description">PlaybackOverlaySupportFragment test</string>
<string name="hgrid">Horizontal Grid</string>
<string name="hgrid_description">HorizontalGridView test</string>
<string name="vgrid">Vertical Grid</string>
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/MainActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/MainActivity.java
index eab5bbe..83e56d6 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/MainActivity.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/MainActivity.java
@@ -26,6 +26,7 @@
import android.support.v17.leanback.widget.GuidedAction;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.content.res.ResourcesCompat;
+
import java.util.List;
/**
@@ -91,10 +92,14 @@
R.string.browseerror_description);
addAction(actions, BrowseErrorSupportActivity.class, R.string.browseerror_support,
R.string.browseerror_support_description);
- addAction(actions, PlaybackOverlayActivity.class, R.string.playback,
+ addAction(actions, PlaybackActivity.class, R.string.playback,
R.string.playback_description);
- addAction(actions, PlaybackOverlaySupportActivity.class, R.string.playback_support,
+ addAction(actions, PlaybackSupportActivity.class, R.string.playback_support,
R.string.playback_support_description);
+ addAction(actions, PlaybackOverlayActivity.class, R.string.playbackoverlay,
+ R.string.playbackoverlay_description);
+ addAction(actions, PlaybackOverlaySupportActivity.class,
+ R.string.playbackoverlay_support, R.string.playbackoverlay_support_description);
addAction(actions, VideoActivity.class, R.string.video_playback,
R.string.playback_description);
addAction(actions, VideoSupportActivity.class, R.string.video_playback_support,
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackActivity.java
new file mode 100644
index 0000000..14a13cd
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackActivity.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.leanback;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Host PlaybackFragment and provide PIP events.
+ */
+public class PlaybackActivity extends Activity {
+ private List<PictureInPictureListener> mListeners = new ArrayList<>();
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.playback_activity);
+ }
+
+ @Override
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+ for (PictureInPictureListener listener : mListeners) {
+ listener.onPictureInPictureModeChanged(isInPictureInPictureMode);
+ }
+ }
+
+ /**
+ * Register a PIP listener.
+ */
+ public void registerPictureInPictureListener(PictureInPictureListener listener) {
+ mListeners.add(listener);
+ }
+
+ /**
+ * Unregister a PIP listener.
+ */
+ public void unregisterPictureInPictureListener(PictureInPictureListener listener) {
+ mListeners.remove(listener);
+ }
+
+ /**
+ * Interface of PIP event on Activity.
+ */
+ public interface PictureInPictureListener {
+ /**
+ * Called when Activity's PIP mode is changed.
+ */
+ void onPictureInPictureModeChanged(boolean isInPictureInPictureMode);
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlGlue.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlGlue.java
new file mode 100644
index 0000000..e04fa46
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlGlue.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.leanback;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.support.v17.leanback.widget.Action;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.PlaybackControlsRow;
+import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.Toast;
+
+abstract class PlaybackControlGlue extends android.support.v17.leanback.media.PlaybackControlGlue {
+ /**
+ * Change the location of the thumbs up/down controls
+ */
+ private static final boolean THUMBS_PRIMARY = true;
+
+ private static final String FAUX_TITLE = "A short song of silence";
+ private static final String FAUX_SUBTITLE = "2014";
+ private static final int FAUX_DURATION = 33 * 1000;
+
+ // These should match the playback service FF behavior
+ private static int[] sFastForwardSpeeds = { 2, 3, 4, 5 };
+
+ private boolean mIsPlaying;
+ private int mSpeed = PlaybackControlGlue.PLAYBACK_SPEED_PAUSED;
+ private long mStartTime;
+ private long mStartPosition = 0;
+
+ private PlaybackControlsRow.RepeatAction mRepeatAction;
+ private PlaybackControlsRow.ThumbsUpAction mThumbsUpAction;
+ private PlaybackControlsRow.ThumbsDownAction mThumbsDownAction;
+ private PlaybackControlsRow.PictureInPictureAction mPipAction;
+
+ private Handler mHandler = new Handler();
+ private final Runnable mUpdateProgressRunnable = new Runnable() {
+ @Override
+ public void run() {
+ updateProgress();
+ mHandler.postDelayed(this, getUpdatePeriod());
+ }
+ };
+
+ PlaybackControlGlue(Context context) {
+ super(context, sFastForwardSpeeds);
+ mThumbsUpAction = new PlaybackControlsRow.ThumbsUpAction(context);
+ mThumbsUpAction.setIndex(PlaybackControlsRow.ThumbsUpAction.OUTLINE);
+ mThumbsDownAction = new PlaybackControlsRow.ThumbsDownAction(context);
+ mThumbsDownAction.setIndex(PlaybackControlsRow.ThumbsDownAction.OUTLINE);
+ mRepeatAction = new PlaybackControlsRow.RepeatAction(context);
+ mPipAction = new PlaybackControlsRow.PictureInPictureAction(context);
+ }
+
+ @Override
+ protected void onCreateSecondaryActions(ArrayObjectAdapter adapter) {
+ if (!THUMBS_PRIMARY) {
+ adapter.add(mThumbsDownAction);
+ }
+ if (android.os.Build.VERSION.SDK_INT > 23) {
+ adapter.add(mPipAction);
+ }
+ adapter.add(mRepeatAction);
+ if (!THUMBS_PRIMARY) {
+ adapter.add(mThumbsUpAction);
+ }
+ }
+
+ @Override
+ protected void onCreatePrimaryActions(SparseArrayObjectAdapter adapter) {
+ if (THUMBS_PRIMARY) {
+ adapter.set(PlaybackControlGlue.ACTION_CUSTOM_LEFT_FIRST, mThumbsUpAction);
+ adapter.set(PlaybackControlGlue.ACTION_CUSTOM_RIGHT_FIRST, mThumbsDownAction);
+ }
+ }
+
+ @Override
+ public void onActionClicked(Action action) {
+ if (shouldDispatchAction(action)) {
+ dispatchAction(action);
+ return;
+ }
+ super.onActionClicked(action);
+ }
+
+ @Override
+ public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
+ if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
+ Action action = getControlsRow().getActionForKeyCode(keyEvent.getKeyCode());
+ if (shouldDispatchAction(action)) {
+ dispatchAction(action);
+ return true;
+ }
+ }
+ return super.onKey(view, keyCode, keyEvent);
+ }
+
+ private boolean shouldDispatchAction(Action action) {
+ return action == mRepeatAction || action == mThumbsUpAction || action == mThumbsDownAction;
+ }
+
+ private void dispatchAction(Action action) {
+ Toast.makeText(getContext(), action.toString(), Toast.LENGTH_SHORT).show();
+ PlaybackControlsRow.MultiAction multiAction = (PlaybackControlsRow.MultiAction) action;
+ multiAction.nextIndex();
+ notifyActionChanged(multiAction);
+ }
+
+ private void notifyActionChanged(PlaybackControlsRow.MultiAction action) {
+ int index;
+ index = getPrimaryActionsAdapter().indexOf(action);
+ if (index >= 0) {
+ getPrimaryActionsAdapter().notifyArrayItemRangeChanged(index, 1);
+ } else {
+ index = getSecondaryActionsAdapter().indexOf(action);
+ if (index >= 0) {
+ getSecondaryActionsAdapter().notifyArrayItemRangeChanged(index, 1);
+ }
+ }
+ }
+
+ private SparseArrayObjectAdapter getPrimaryActionsAdapter() {
+ return (SparseArrayObjectAdapter) getControlsRow().getPrimaryActionsAdapter();
+ }
+
+ private ArrayObjectAdapter getSecondaryActionsAdapter() {
+ return (ArrayObjectAdapter) getControlsRow().getSecondaryActionsAdapter();
+ }
+
+ @Override
+ public boolean hasValidMedia() {
+ return true;
+ }
+
+ @Override
+ public boolean isMediaPlaying() {
+ return mIsPlaying;
+ }
+
+ @Override
+ public CharSequence getMediaTitle() {
+ return FAUX_TITLE;
+ }
+
+ @Override
+ public CharSequence getMediaSubtitle() {
+ return FAUX_SUBTITLE;
+ }
+
+ @Override
+ public int getMediaDuration() {
+ return FAUX_DURATION;
+ }
+
+ @Override
+ public Drawable getMediaArt() {
+ return null;
+ }
+
+ @Override
+ public long getSupportedActions() {
+ return PlaybackControlGlue.ACTION_PLAY_PAUSE
+ | PlaybackControlGlue.ACTION_FAST_FORWARD
+ | PlaybackControlGlue.ACTION_REWIND;
+ }
+
+ @Override
+ public int getCurrentSpeedId() {
+ return mSpeed;
+ }
+
+ @Override
+ public int getCurrentPosition() {
+ int speed;
+ if (mSpeed == PlaybackControlGlue.PLAYBACK_SPEED_PAUSED) {
+ speed = 0;
+ } else if (mSpeed == PlaybackControlGlue.PLAYBACK_SPEED_NORMAL) {
+ speed = 1;
+ } else if (mSpeed >= PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0) {
+ int index = mSpeed - PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0;
+ speed = getFastForwardSpeeds()[index];
+ } else if (mSpeed <= -PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0) {
+ int index = -mSpeed - PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0;
+ speed = -getRewindSpeeds()[index];
+ } else {
+ return -1;
+ }
+ long position = mStartPosition + (System.currentTimeMillis() - mStartTime) * speed;
+ if (position > getMediaDuration()) {
+ position = getMediaDuration();
+ onPlaybackComplete(true);
+ } else if (position < 0) {
+ position = 0;
+ onPlaybackComplete(false);
+ }
+ return (int) position;
+ }
+
+ void onPlaybackComplete(final boolean ended) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mRepeatAction.getIndex() == PlaybackControlsRow.RepeatAction.NONE) {
+ pause();
+ } else {
+ play(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL);
+ }
+ mStartPosition = 0;
+ onStateChanged();
+ }
+ });
+ }
+
+ @Override
+ public void play(int speed) {
+ if (speed == mSpeed) {
+ return;
+ }
+ mStartPosition = getCurrentPosition();
+ mSpeed = speed;
+ mIsPlaying = true;
+ mStartTime = System.currentTimeMillis();
+ }
+
+ @Override
+ public void pause() {
+ if (mSpeed == PlaybackControlGlue.PLAYBACK_SPEED_PAUSED) {
+ return;
+ }
+ mStartPosition = getCurrentPosition();
+ mSpeed = PlaybackControlGlue.PLAYBACK_SPEED_PAUSED;
+ mIsPlaying = false;
+ }
+
+ @Override
+ public void next() {
+ // Not supported
+ }
+
+ @Override
+ public void previous() {
+ // Not supported
+ }
+
+ @Override
+ public void enableProgressUpdating(boolean enable) {
+ mHandler.removeCallbacks(mUpdateProgressRunnable);
+ if (enable) {
+ mUpdateProgressRunnable.run();
+ }
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlHelper.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlHelper.java
index 09892da..df6995e 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlHelper.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlHelper.java
@@ -19,17 +19,19 @@
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import android.support.v17.leanback.media.MediaPlayerGlue;
-import android.support.v17.leanback.media.PlaybackControlGlue;
+import android.support.v17.leanback.app.PlaybackControlGlue;
import android.support.v17.leanback.widget.Action;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.ControlButtonPresenterSelector;
import android.support.v17.leanback.widget.PlaybackControlsRow;
+import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
+import android.support.v17.leanback.widget.PresenterSelector;
import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Toast;
-abstract class PlaybackControlHelper extends MediaPlayerGlue {
+abstract class PlaybackControlHelper extends PlaybackControlGlue {
/**
* Change the location of the thumbs up/down controls
*/
@@ -52,17 +54,17 @@
private PlaybackControlsRow.ThumbsDownAction mThumbsDownAction;
private PlaybackControlsRow.PictureInPictureAction mPipAction;
- private static Handler sHandler = new Handler();
+ private Handler mHandler = new Handler();
private final Runnable mUpdateProgressRunnable = new Runnable() {
@Override
public void run() {
updateProgress();
- sHandler.postDelayed(this, getUpdatePeriod());
+ mHandler.postDelayed(this, getUpdatePeriod());
}
};
- PlaybackControlHelper(Context context) {
- super(context, sFastForwardSpeeds, sFastForwardSpeeds);
+ PlaybackControlHelper(Context context, PlaybackOverlayFragment fragment) {
+ super(context, fragment, sFastForwardSpeeds);
mThumbsUpAction = new PlaybackControlsRow.ThumbsUpAction(context);
mThumbsUpAction.setIndex(PlaybackControlsRow.ThumbsUpAction.OUTLINE);
mThumbsDownAction = new PlaybackControlsRow.ThumbsDownAction(context);
@@ -72,26 +74,34 @@
}
@Override
- protected void onCreateSecondaryActions(ArrayObjectAdapter secondaryActionsAdapter) {
+ public PlaybackControlsRowPresenter createControlsRowAndPresenter() {
+ PlaybackControlsRowPresenter presenter = super.createControlsRowAndPresenter();
+
+ ArrayObjectAdapter adapter = new ArrayObjectAdapter(new ControlButtonPresenterSelector());
+ getControlsRow().setSecondaryActionsAdapter(adapter);
if (!THUMBS_PRIMARY) {
- secondaryActionsAdapter.add(mThumbsDownAction);
+ adapter.add(mThumbsDownAction);
}
if (android.os.Build.VERSION.SDK_INT > 23) {
- secondaryActionsAdapter.add(mPipAction);
+ adapter.add(mPipAction);
}
- secondaryActionsAdapter.add(mRepeatAction);
+ adapter.add(mRepeatAction);
if (!THUMBS_PRIMARY) {
- secondaryActionsAdapter.add(mThumbsUpAction);
+ adapter.add(mThumbsUpAction);
}
+
+ return presenter;
}
@Override
- protected void onCreatePrimaryActions(SparseArrayObjectAdapter adapter) {
- super.onCreatePrimaryActions(adapter);
+ protected SparseArrayObjectAdapter createPrimaryActionsAdapter(
+ PresenterSelector presenterSelector) {
+ SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter(presenterSelector);
if (THUMBS_PRIMARY) {
adapter.set(PlaybackControlGlue.ACTION_CUSTOM_LEFT_FIRST, mThumbsUpAction);
adapter.set(PlaybackControlGlue.ACTION_CUSTOM_RIGHT_FIRST, mThumbsDownAction);
}
+ return adapter;
}
@Override
@@ -218,13 +228,13 @@
}
void onPlaybackComplete(final boolean ended) {
- sHandler.post(new Runnable() {
+ mHandler.post(new Runnable() {
@Override
public void run() {
if (mRepeatAction.getIndex() == PlaybackControlsRow.RepeatAction.NONE) {
- pause();
+ pausePlayback();
} else {
- play(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL);
+ startPlayback(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL);
}
mStartPosition = 0;
onStateChanged();
@@ -233,7 +243,7 @@
}
@Override
- public void play(int speed) {
+ protected void startPlayback(int speed) {
if (speed == mSpeed) {
return;
}
@@ -244,7 +254,7 @@
}
@Override
- public void pause() {
+ protected void pausePlayback() {
if (mSpeed == PlaybackControlGlue.PLAYBACK_SPEED_PAUSED) {
return;
}
@@ -254,20 +264,20 @@
}
@Override
- public void next() {
+ protected void skipToNext() {
// Not supported
}
@Override
- public void previous() {
+ protected void skipToPrevious() {
// Not supported
}
@Override
public void enableProgressUpdating(boolean enable) {
- sHandler.removeCallbacks(mUpdateProgressRunnable);
+ mHandler.removeCallbacks(mUpdateProgressRunnable);
if (enable) {
mUpdateProgressRunnable.run();
}
}
-}
+};
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlSupportHelper.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlSupportHelper.java
new file mode 100644
index 0000000..e7afb27
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackControlSupportHelper.java
@@ -0,0 +1,286 @@
+// CHECKSTYLE:OFF Generated code
+/* This file is auto-generated from PlaybackControlHelper.java. DO NOT MODIFY. */
+
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.example.android.leanback;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.support.v17.leanback.app.PlaybackControlSupportGlue;
+import android.support.v17.leanback.widget.Action;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.ControlButtonPresenterSelector;
+import android.support.v17.leanback.widget.PlaybackControlsRow;
+import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
+import android.support.v17.leanback.widget.PresenterSelector;
+import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.Toast;
+
+abstract class PlaybackControlSupportHelper extends PlaybackControlSupportGlue {
+ /**
+ * Change the location of the thumbs up/down controls
+ */
+ private static final boolean THUMBS_PRIMARY = true;
+
+ private static final String FAUX_TITLE = "A short song of silence";
+ private static final String FAUX_SUBTITLE = "2014";
+ private static final int FAUX_DURATION = 33 * 1000;
+
+ // These should match the playback service FF behavior
+ private static int[] sFastForwardSpeeds = { 2, 3, 4, 5 };
+
+ private boolean mIsPlaying;
+ private int mSpeed = PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED;
+ private long mStartTime;
+ private long mStartPosition = 0;
+
+ private PlaybackControlsRow.RepeatAction mRepeatAction;
+ private PlaybackControlsRow.ThumbsUpAction mThumbsUpAction;
+ private PlaybackControlsRow.ThumbsDownAction mThumbsDownAction;
+ private PlaybackControlsRow.PictureInPictureAction mPipAction;
+
+ private Handler mHandler = new Handler();
+ private final Runnable mUpdateProgressRunnable = new Runnable() {
+ @Override
+ public void run() {
+ updateProgress();
+ mHandler.postDelayed(this, getUpdatePeriod());
+ }
+ };
+
+ PlaybackControlSupportHelper(Context context, PlaybackOverlaySupportFragment fragment) {
+ super(context, fragment, sFastForwardSpeeds);
+ mThumbsUpAction = new PlaybackControlsRow.ThumbsUpAction(context);
+ mThumbsUpAction.setIndex(PlaybackControlsRow.ThumbsUpAction.OUTLINE);
+ mThumbsDownAction = new PlaybackControlsRow.ThumbsDownAction(context);
+ mThumbsDownAction.setIndex(PlaybackControlsRow.ThumbsDownAction.OUTLINE);
+ mRepeatAction = new PlaybackControlsRow.RepeatAction(context);
+ mPipAction = new PlaybackControlsRow.PictureInPictureAction(context);
+ }
+
+ @Override
+ public PlaybackControlsRowPresenter createControlsRowAndPresenter() {
+ PlaybackControlsRowPresenter presenter = super.createControlsRowAndPresenter();
+
+ ArrayObjectAdapter adapter = new ArrayObjectAdapter(new ControlButtonPresenterSelector());
+ getControlsRow().setSecondaryActionsAdapter(adapter);
+ if (!THUMBS_PRIMARY) {
+ adapter.add(mThumbsDownAction);
+ }
+ if (android.os.Build.VERSION.SDK_INT > 23) {
+ adapter.add(mPipAction);
+ }
+ adapter.add(mRepeatAction);
+ if (!THUMBS_PRIMARY) {
+ adapter.add(mThumbsUpAction);
+ }
+
+ return presenter;
+ }
+
+ @Override
+ protected SparseArrayObjectAdapter createPrimaryActionsAdapter(
+ PresenterSelector presenterSelector) {
+ SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter(presenterSelector);
+ if (THUMBS_PRIMARY) {
+ adapter.set(PlaybackControlSupportGlue.ACTION_CUSTOM_LEFT_FIRST, mThumbsUpAction);
+ adapter.set(PlaybackControlSupportGlue.ACTION_CUSTOM_RIGHT_FIRST, mThumbsDownAction);
+ }
+ return adapter;
+ }
+
+ @Override
+ public void onActionClicked(Action action) {
+ if (shouldDispatchAction(action)) {
+ dispatchAction(action);
+ return;
+ }
+ super.onActionClicked(action);
+ }
+
+ @Override
+ public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
+ if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
+ Action action = getControlsRow().getActionForKeyCode(keyEvent.getKeyCode());
+ if (shouldDispatchAction(action)) {
+ dispatchAction(action);
+ return true;
+ }
+ }
+ return super.onKey(view, keyCode, keyEvent);
+ }
+
+ private boolean shouldDispatchAction(Action action) {
+ return action == mRepeatAction || action == mThumbsUpAction || action == mThumbsDownAction;
+ }
+
+ private void dispatchAction(Action action) {
+ Toast.makeText(getContext(), action.toString(), Toast.LENGTH_SHORT).show();
+ PlaybackControlsRow.MultiAction multiAction = (PlaybackControlsRow.MultiAction) action;
+ multiAction.nextIndex();
+ notifyActionChanged(multiAction);
+ }
+
+ private void notifyActionChanged(PlaybackControlsRow.MultiAction action) {
+ int index;
+ index = getPrimaryActionsAdapter().indexOf(action);
+ if (index >= 0) {
+ getPrimaryActionsAdapter().notifyArrayItemRangeChanged(index, 1);
+ } else {
+ index = getSecondaryActionsAdapter().indexOf(action);
+ if (index >= 0) {
+ getSecondaryActionsAdapter().notifyArrayItemRangeChanged(index, 1);
+ }
+ }
+ }
+
+ private SparseArrayObjectAdapter getPrimaryActionsAdapter() {
+ return (SparseArrayObjectAdapter) getControlsRow().getPrimaryActionsAdapter();
+ }
+
+ private ArrayObjectAdapter getSecondaryActionsAdapter() {
+ return (ArrayObjectAdapter) getControlsRow().getSecondaryActionsAdapter();
+ }
+
+ @Override
+ public boolean hasValidMedia() {
+ return true;
+ }
+
+ @Override
+ public boolean isMediaPlaying() {
+ return mIsPlaying;
+ }
+
+ @Override
+ public CharSequence getMediaTitle() {
+ return FAUX_TITLE;
+ }
+
+ @Override
+ public CharSequence getMediaSubtitle() {
+ return FAUX_SUBTITLE;
+ }
+
+ @Override
+ public int getMediaDuration() {
+ return FAUX_DURATION;
+ }
+
+ @Override
+ public Drawable getMediaArt() {
+ return null;
+ }
+
+ @Override
+ public long getSupportedActions() {
+ return PlaybackControlSupportGlue.ACTION_PLAY_PAUSE |
+ PlaybackControlSupportGlue.ACTION_FAST_FORWARD |
+ PlaybackControlSupportGlue.ACTION_REWIND;
+ }
+
+ @Override
+ public int getCurrentSpeedId() {
+ return mSpeed;
+ }
+
+ @Override
+ public int getCurrentPosition() {
+ int speed;
+ if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED) {
+ speed = 0;
+ } else if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_NORMAL) {
+ speed = 1;
+ } else if (mSpeed >= PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0) {
+ int index = mSpeed - PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0;
+ speed = getFastForwardSpeeds()[index];
+ } else if (mSpeed <= -PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0) {
+ int index = -mSpeed - PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0;
+ speed = -getRewindSpeeds()[index];
+ } else {
+ return -1;
+ }
+ long position = mStartPosition +
+ (System.currentTimeMillis() - mStartTime) * speed;
+ if (position > getMediaDuration()) {
+ position = getMediaDuration();
+ onPlaybackComplete(true);
+ } else if (position < 0) {
+ position = 0;
+ onPlaybackComplete(false);
+ }
+ return (int) position;
+ }
+
+ void onPlaybackComplete(final boolean ended) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mRepeatAction.getIndex() == PlaybackControlsRow.RepeatAction.NONE) {
+ pausePlayback();
+ } else {
+ startPlayback(PlaybackControlSupportGlue.PLAYBACK_SPEED_NORMAL);
+ }
+ mStartPosition = 0;
+ onStateChanged();
+ }
+ });
+ }
+
+ @Override
+ protected void startPlayback(int speed) {
+ if (speed == mSpeed) {
+ return;
+ }
+ mStartPosition = getCurrentPosition();
+ mSpeed = speed;
+ mIsPlaying = true;
+ mStartTime = System.currentTimeMillis();
+ }
+
+ @Override
+ protected void pausePlayback() {
+ if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED) {
+ return;
+ }
+ mStartPosition = getCurrentPosition();
+ mSpeed = PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED;
+ mIsPlaying = false;
+ }
+
+ @Override
+ protected void skipToNext() {
+ // Not supported
+ }
+
+ @Override
+ protected void skipToPrevious() {
+ // Not supported
+ }
+
+ @Override
+ public void enableProgressUpdating(boolean enable) {
+ mHandler.removeCallbacks(mUpdateProgressRunnable);
+ if (enable) {
+ mUpdateProgressRunnable.run();
+ }
+ }
+};
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackFragment.java
new file mode 100644
index 0000000..a29a995
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackFragment.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.leanback;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v17.leanback.app.PlaybackFragmentGlueHost;
+import android.support.v17.leanback.widget.Action;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.PlaybackControlsRow;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.PresenterSelector;
+import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
+import android.util.Log;
+
+/**
+ * Example of PlaybackFragment working with a PlaybackControlGlue.
+ */
+public class PlaybackFragment
+ extends android.support.v17.leanback.app.PlaybackFragment
+ implements PlaybackActivity.PictureInPictureListener {
+ private static final String TAG = "leanback.PlaybackControlsFragment";
+
+ /**
+ * Change this to choose a different overlay background.
+ */
+ private static final int BACKGROUND_TYPE = PlaybackFragment.BG_LIGHT;
+
+ /**
+ * Change the number of related content rows.
+ */
+ private static final int RELATED_CONTENT_ROWS = 3;
+
+ /**
+ * Change this to select hidden
+ */
+ private static final boolean SECONDARY_HIDDEN = false;
+
+ private static final int ROW_CONTROLS = 0;
+
+ private PlaybackControlGlue mGlue;
+ private ListRowPresenter mListRowPresenter;
+
+ public SparseArrayObjectAdapter getAdapter() {
+ return (SparseArrayObjectAdapter) super.getAdapter();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+
+ setBackgroundType(BACKGROUND_TYPE);
+
+ createComponents(getActivity());
+ }
+
+ private void createComponents(Context context) {
+ mGlue = new PlaybackControlGlue(context) {
+ @Override
+ public int getUpdatePeriod() {
+ int totalTime = getControlsRow().getTotalTime();
+ if (getView() == null || getView().getWidth() == 0 || totalTime <= 0) {
+ return 1000;
+ }
+ return Math.max(16, totalTime / getView().getWidth());
+ }
+
+ @Override
+ public void onActionClicked(Action action) {
+ if (action.getId() == R.id.lb_control_picture_in_picture) {
+ getActivity().enterPictureInPictureMode();
+ return;
+ }
+ super.onActionClicked(action);
+ }
+
+ @Override
+ protected void onCreateControlsRowAndPresenter() {
+ super.onCreateControlsRowAndPresenter();
+ getControlsRowPresenter().setSecondaryActionsHidden(SECONDARY_HIDDEN);
+ }
+ };
+
+ mGlue.setHost(new PlaybackFragmentGlueHost(this));
+ mListRowPresenter = new ListRowPresenter();
+
+ setAdapter(new SparseArrayObjectAdapter(new PresenterSelector() {
+ @Override
+ public Presenter getPresenter(Object object) {
+ if (object instanceof PlaybackControlsRow) {
+ return mGlue.getControlsRowPresenter();
+ } else if (object instanceof ListRow) {
+ return mListRowPresenter;
+ }
+ throw new IllegalArgumentException("Unhandled object: " + object);
+ }
+ }));
+
+ // Add the controls row
+ getAdapter().set(ROW_CONTROLS, mGlue.getControlsRow());
+
+ // Add related content rows
+ for (int i = 0; i < RELATED_CONTENT_ROWS; ++i) {
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new StringPresenter());
+ listRowAdapter.add("Some related content");
+ listRowAdapter.add("Other related content");
+ HeaderItem header = new HeaderItem(i, "Row " + i);
+ getAdapter().set(ROW_CONTROLS + 1 + i, new ListRow(header, listRowAdapter));
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ ((PlaybackActivity) getActivity()).registerPictureInPictureListener(this);
+ }
+
+ @Override
+ public void onStop() {
+ ((PlaybackActivity) getActivity()).unregisterPictureInPictureListener(this);
+ super.onStop();
+ }
+
+ @Override
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+ if (isInPictureInPictureMode) {
+ // Hide the controls in picture-in-picture mode.
+ setFadingEnabled(true);
+ fadeOut();
+ } else {
+ setFadingEnabled(mGlue.isMediaPlaying());
+ }
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java
index 1701153..1531d14 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlayFragment.java
@@ -15,28 +15,31 @@
import android.content.Context;
import android.os.Bundle;
-import android.support.v17.leanback.app.PlaybackFragment;
-import android.support.v17.leanback.app.PlaybackFragmentGlueHost;
import android.support.v17.leanback.widget.Action;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
import android.support.v17.leanback.widget.HeaderItem;
import android.support.v17.leanback.widget.ListRow;
import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.OnItemViewClickedListener;
+import android.support.v17.leanback.widget.OnItemViewSelectedListener;
import android.support.v17.leanback.widget.PlaybackControlsRow;
+import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.PresenterSelector;
+import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.RowPresenter;
import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
import android.util.Log;
public class PlaybackOverlayFragment
- extends android.support.v17.leanback.app.PlaybackFragment
+ extends android.support.v17.leanback.app.PlaybackOverlayFragment
implements PlaybackOverlayActivity.PictureInPictureListener {
private static final String TAG = "leanback.PlaybackControlsFragment";
/**
* Change this to choose a different overlay background.
*/
- private static final int BACKGROUND_TYPE = PlaybackFragment.BG_LIGHT;
+ private static final int BACKGROUND_TYPE = PlaybackOverlayFragment.BG_LIGHT;
/**
* Change the number of related content rows.
@@ -51,8 +54,29 @@
private static final int ROW_CONTROLS = 0;
private PlaybackControlHelper mGlue;
+ private PlaybackControlsRowPresenter mPlaybackControlsRowPresenter;
private ListRowPresenter mListRowPresenter;
+ private OnItemViewClickedListener mOnItemViewClickedListener = new OnItemViewClickedListener() {
+ @Override
+ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ Log.i(TAG, "onItemClicked: " + item + " row " + row);
+ if (item instanceof Action) {
+ mGlue.onActionClicked((Action) item);
+ }
+ }
+ };
+
+ private OnItemViewSelectedListener mOnItemViewSelectedListener =
+ new OnItemViewSelectedListener() {
+ @Override
+ public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ Log.i(TAG, "onItemSelected: " + item + " row " + row);
+ }
+ };
+
public SparseArrayObjectAdapter getAdapter() {
return (SparseArrayObjectAdapter) super.getAdapter();
}
@@ -63,12 +87,13 @@
super.onCreate(savedInstanceState);
setBackgroundType(BACKGROUND_TYPE);
+ setOnItemViewSelectedListener(mOnItemViewSelectedListener);
createComponents(getActivity());
}
private void createComponents(Context context) {
- mGlue = new PlaybackControlHelper(context) {
+ mGlue = new PlaybackControlHelper(context, this) {
@Override
public int getUpdatePeriod() {
int totalTime = getControlsRow().getTotalTime();
@@ -79,6 +104,17 @@
}
@Override
+ protected void onRowChanged(PlaybackControlsRow row) {
+ if (getAdapter() == null) {
+ return;
+ }
+ int index = getAdapter().indexOf(row);
+ if (index >= 0) {
+ getAdapter().notifyArrayItemRangeChanged(index, 1);
+ }
+ }
+
+ @Override
public void onActionClicked(Action action) {
if (action.getId() == R.id.lb_control_picture_in_picture) {
getActivity().enterPictureInPictureMode();
@@ -86,22 +122,19 @@
}
super.onActionClicked(action);
}
-
- @Override
- protected void onCreateControlsRowAndPresenter() {
- super.onCreateControlsRowAndPresenter();
- getControlsRowPresenter().setSecondaryActionsHidden(SECONDARY_HIDDEN);
- }
};
- mGlue.setHost(new PlaybackFragmentGlueHost(this));
+ mGlue.setOnItemViewClickedListener(mOnItemViewClickedListener);
+
+ mPlaybackControlsRowPresenter = mGlue.createControlsRowAndPresenter();
+ mPlaybackControlsRowPresenter.setSecondaryActionsHidden(SECONDARY_HIDDEN);
mListRowPresenter = new ListRowPresenter();
setAdapter(new SparseArrayObjectAdapter(new PresenterSelector() {
@Override
public Presenter getPresenter(Object object) {
if (object instanceof PlaybackControlsRow) {
- return mGlue.getControlsRowPresenter();
+ return mPlaybackControlsRowPresenter;
} else if (object instanceof ListRow) {
return mListRowPresenter;
}
@@ -120,16 +153,20 @@
HeaderItem header = new HeaderItem(i, "Row " + i);
getAdapter().set(ROW_CONTROLS + 1 + i, new ListRow(header, listRowAdapter));
}
+
}
@Override
public void onStart() {
super.onStart();
+ mGlue.setFadingEnabled(true);
+ mGlue.enableProgressUpdating(true);
((PlaybackOverlayActivity) getActivity()).registerPictureInPictureListener(this);
}
@Override
public void onStop() {
+ mGlue.enableProgressUpdating(false);
((PlaybackOverlayActivity) getActivity()).unregisterPictureInPictureListener(this);
super.onStop();
}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportFragment.java
index baa2cb7..7a33493 100644
--- a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportFragment.java
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackOverlaySupportFragment.java
@@ -18,28 +18,31 @@
import android.content.Context;
import android.os.Bundle;
-import android.support.v17.leanback.app.PlaybackSupportFragment;
-import android.support.v17.leanback.app.PlaybackSupportFragmentGlueHost;
import android.support.v17.leanback.widget.Action;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
import android.support.v17.leanback.widget.HeaderItem;
import android.support.v17.leanback.widget.ListRow;
import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.OnItemViewClickedListener;
+import android.support.v17.leanback.widget.OnItemViewSelectedListener;
import android.support.v17.leanback.widget.PlaybackControlsRow;
+import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.PresenterSelector;
+import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.RowPresenter;
import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
import android.util.Log;
public class PlaybackOverlaySupportFragment
- extends android.support.v17.leanback.app.PlaybackSupportFragment
+ extends android.support.v17.leanback.app.PlaybackOverlaySupportFragment
implements PlaybackOverlaySupportActivity.PictureInPictureListener {
private static final String TAG = "leanback.PlaybackControlsFragment";
/**
* Change this to choose a different overlay background.
*/
- private static final int BACKGROUND_TYPE = PlaybackSupportFragment.BG_LIGHT;
+ private static final int BACKGROUND_TYPE = PlaybackOverlaySupportFragment.BG_LIGHT;
/**
* Change the number of related content rows.
@@ -53,9 +56,30 @@
private static final int ROW_CONTROLS = 0;
- private PlaybackControlHelper mGlue;
+ private PlaybackControlSupportHelper mGlue;
+ private PlaybackControlsRowPresenter mPlaybackControlsRowPresenter;
private ListRowPresenter mListRowPresenter;
+ private OnItemViewClickedListener mOnItemViewClickedListener = new OnItemViewClickedListener() {
+ @Override
+ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ Log.i(TAG, "onItemClicked: " + item + " row " + row);
+ if (item instanceof Action) {
+ mGlue.onActionClicked((Action) item);
+ }
+ }
+ };
+
+ private OnItemViewSelectedListener mOnItemViewSelectedListener =
+ new OnItemViewSelectedListener() {
+ @Override
+ public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ Log.i(TAG, "onItemSelected: " + item + " row " + row);
+ }
+ };
+
public SparseArrayObjectAdapter getAdapter() {
return (SparseArrayObjectAdapter) super.getAdapter();
}
@@ -66,12 +90,13 @@
super.onCreate(savedInstanceState);
setBackgroundType(BACKGROUND_TYPE);
+ setOnItemViewSelectedListener(mOnItemViewSelectedListener);
createComponents(getActivity());
}
private void createComponents(Context context) {
- mGlue = new PlaybackControlHelper(context) {
+ mGlue = new PlaybackControlSupportHelper(context, this) {
@Override
public int getUpdatePeriod() {
int totalTime = getControlsRow().getTotalTime();
@@ -82,6 +107,17 @@
}
@Override
+ protected void onRowChanged(PlaybackControlsRow row) {
+ if (getAdapter() == null) {
+ return;
+ }
+ int index = getAdapter().indexOf(row);
+ if (index >= 0) {
+ getAdapter().notifyArrayItemRangeChanged(index, 1);
+ }
+ }
+
+ @Override
public void onActionClicked(Action action) {
if (action.getId() == R.id.lb_control_picture_in_picture) {
getActivity().enterPictureInPictureMode();
@@ -89,22 +125,19 @@
}
super.onActionClicked(action);
}
-
- @Override
- protected void onCreateControlsRowAndPresenter() {
- super.onCreateControlsRowAndPresenter();
- getControlsRowPresenter().setSecondaryActionsHidden(SECONDARY_HIDDEN);
- }
};
- mGlue.setHost(new PlaybackSupportFragmentGlueHost(this));
+ mGlue.setOnItemViewClickedListener(mOnItemViewClickedListener);
+
+ mPlaybackControlsRowPresenter = mGlue.createControlsRowAndPresenter();
+ mPlaybackControlsRowPresenter.setSecondaryActionsHidden(SECONDARY_HIDDEN);
mListRowPresenter = new ListRowPresenter();
setAdapter(new SparseArrayObjectAdapter(new PresenterSelector() {
@Override
public Presenter getPresenter(Object object) {
if (object instanceof PlaybackControlsRow) {
- return mGlue.getControlsRowPresenter();
+ return mPlaybackControlsRowPresenter;
} else if (object instanceof ListRow) {
return mListRowPresenter;
}
@@ -123,16 +156,20 @@
HeaderItem header = new HeaderItem(i, "Row " + i);
getAdapter().set(ROW_CONTROLS + 1 + i, new ListRow(header, listRowAdapter));
}
+
}
@Override
public void onStart() {
super.onStart();
+ mGlue.setFadingEnabled(true);
+ mGlue.enableProgressUpdating(true);
((PlaybackOverlaySupportActivity) getActivity()).registerPictureInPictureListener(this);
}
@Override
public void onStop() {
+ mGlue.enableProgressUpdating(false);
((PlaybackOverlaySupportActivity) getActivity()).unregisterPictureInPictureListener(this);
super.onStop();
}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackSupportActivity.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackSupportActivity.java
new file mode 100644
index 0000000..069b37c
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackSupportActivity.java
@@ -0,0 +1,71 @@
+// CHECKSTYLE:OFF Generated code
+/* This file is auto-generated from PlaybackActivity.java. DO NOT MODIFY. */
+
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.leanback;
+
+import android.support.v4.app.FragmentActivity;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Host PlaybackFragment and provide PIP events.
+ */
+public class PlaybackSupportActivity extends FragmentActivity {
+ private List<PictureInPictureListener> mListeners = new ArrayList<>();
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.playback_activity_support);
+ }
+
+ @Override
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+ for (PictureInPictureListener listener : mListeners) {
+ listener.onPictureInPictureModeChanged(isInPictureInPictureMode);
+ }
+ }
+
+ /**
+ * Register a PIP listener.
+ */
+ public void registerPictureInPictureListener(PictureInPictureListener listener) {
+ mListeners.add(listener);
+ }
+
+ /**
+ * Unregister a PIP listener.
+ */
+ public void unregisterPictureInPictureListener(PictureInPictureListener listener) {
+ mListeners.remove(listener);
+ }
+
+ /**
+ * Interface of PIP event on Activity.
+ */
+ public interface PictureInPictureListener {
+ /**
+ * Called when Activity's PIP mode is changed.
+ */
+ void onPictureInPictureModeChanged(boolean isInPictureInPictureMode);
+ }
+}
diff --git a/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackSupportFragment.java b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackSupportFragment.java
new file mode 100644
index 0000000..6d2fa51
--- /dev/null
+++ b/samples/SupportLeanbackDemos/src/com/example/android/leanback/PlaybackSupportFragment.java
@@ -0,0 +1,155 @@
+// CHECKSTYLE:OFF Generated code
+/* This file is auto-generated from PlaybackFragment.java. DO NOT MODIFY. */
+
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.leanback;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v17.leanback.app.PlaybackSupportFragmentGlueHost;
+import android.support.v17.leanback.widget.Action;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.PlaybackControlsRow;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.PresenterSelector;
+import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
+import android.util.Log;
+
+/**
+ * Example of PlaybackSupportFragment working with a PlaybackControlGlue.
+ */
+public class PlaybackSupportFragment
+ extends android.support.v17.leanback.app.PlaybackSupportFragment
+ implements PlaybackSupportActivity.PictureInPictureListener {
+ private static final String TAG = "leanback.PlaybackControlsFragment";
+
+ /**
+ * Change this to choose a different overlay background.
+ */
+ private static final int BACKGROUND_TYPE = PlaybackSupportFragment.BG_LIGHT;
+
+ /**
+ * Change the number of related content rows.
+ */
+ private static final int RELATED_CONTENT_ROWS = 3;
+
+ /**
+ * Change this to select hidden
+ */
+ private static final boolean SECONDARY_HIDDEN = false;
+
+ private static final int ROW_CONTROLS = 0;
+
+ private PlaybackControlGlue mGlue;
+ private ListRowPresenter mListRowPresenter;
+
+ public SparseArrayObjectAdapter getAdapter() {
+ return (SparseArrayObjectAdapter) super.getAdapter();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+
+ setBackgroundType(BACKGROUND_TYPE);
+
+ createComponents(getActivity());
+ }
+
+ private void createComponents(Context context) {
+ mGlue = new PlaybackControlGlue(context) {
+ @Override
+ public int getUpdatePeriod() {
+ int totalTime = getControlsRow().getTotalTime();
+ if (getView() == null || getView().getWidth() == 0 || totalTime <= 0) {
+ return 1000;
+ }
+ return Math.max(16, totalTime / getView().getWidth());
+ }
+
+ @Override
+ public void onActionClicked(Action action) {
+ if (action.getId() == R.id.lb_control_picture_in_picture) {
+ getActivity().enterPictureInPictureMode();
+ return;
+ }
+ super.onActionClicked(action);
+ }
+
+ @Override
+ protected void onCreateControlsRowAndPresenter() {
+ super.onCreateControlsRowAndPresenter();
+ getControlsRowPresenter().setSecondaryActionsHidden(SECONDARY_HIDDEN);
+ }
+ };
+
+ mGlue.setHost(new PlaybackSupportFragmentGlueHost(this));
+ mListRowPresenter = new ListRowPresenter();
+
+ setAdapter(new SparseArrayObjectAdapter(new PresenterSelector() {
+ @Override
+ public Presenter getPresenter(Object object) {
+ if (object instanceof PlaybackControlsRow) {
+ return mGlue.getControlsRowPresenter();
+ } else if (object instanceof ListRow) {
+ return mListRowPresenter;
+ }
+ throw new IllegalArgumentException("Unhandled object: " + object);
+ }
+ }));
+
+ // Add the controls row
+ getAdapter().set(ROW_CONTROLS, mGlue.getControlsRow());
+
+ // Add related content rows
+ for (int i = 0; i < RELATED_CONTENT_ROWS; ++i) {
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new StringPresenter());
+ listRowAdapter.add("Some related content");
+ listRowAdapter.add("Other related content");
+ HeaderItem header = new HeaderItem(i, "Row " + i);
+ getAdapter().set(ROW_CONTROLS + 1 + i, new ListRow(header, listRowAdapter));
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ ((PlaybackSupportActivity) getActivity()).registerPictureInPictureListener(this);
+ }
+
+ @Override
+ public void onStop() {
+ ((PlaybackSupportActivity) getActivity()).unregisterPictureInPictureListener(this);
+ super.onStop();
+ }
+
+ @Override
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+ if (isInPictureInPictureMode) {
+ // Hide the controls in picture-in-picture mode.
+ setFadingEnabled(true);
+ fadeOut();
+ } else {
+ setFadingEnabled(mGlue.isMediaPlaying());
+ }
+ }
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java b/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java
index 56bd8da..b16f432 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlGlue.java
@@ -20,6 +20,7 @@
import android.support.v17.leanback.widget.OnItemViewClickedListener;
import android.support.v17.leanback.widget.PlaybackControlsRow;
import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
+import android.support.v17.leanback.widget.PlaybackRowPresenter;
import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.PresenterSelector;
import android.support.v17.leanback.widget.Row;
@@ -276,9 +277,24 @@
static final class PlaybackGlueHostOld extends PlaybackGlueHost {
final PlaybackOverlayFragment mFragment;
PlaybackControlGlue mGlue;
+ OnActionClickedListener mActionClickedListener;
public PlaybackGlueHostOld(PlaybackOverlayFragment fragment) {
mFragment = fragment;
+ mFragment.setOnItemViewClickedListener(new OnItemViewClickedListener() {
+ @Override
+ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ if (item instanceof Action
+ && rowViewHolder instanceof PlaybackRowPresenter.ViewHolder
+ && mActionClickedListener != null) {
+ mActionClickedListener.onActionClicked((Action) item);
+ } else if (mGlue != null && mGlue.getOnItemViewClickedListener() != null) {
+ mGlue.getOnItemViewClickedListener().onItemClicked(itemViewHolder,
+ item, rowViewHolder, row);
+ }
+ }
+ });
}
@Override
@@ -302,19 +318,7 @@
@Override
public void setOnActionClickedListener(final OnActionClickedListener listener) {
- mFragment.setOnItemViewClickedListener(new OnItemViewClickedListener() {
- @Override
- public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
- RowPresenter.ViewHolder rowViewHolder, Row row) {
- if (item instanceof Action) {
- listener.onActionClicked((Action)item);
- if (mGlue.getOnItemViewClickedListener() != null) {
- mGlue.getOnItemViewClickedListener().onItemClicked(itemViewHolder,
- item, rowViewHolder, row);
- }
- }
- }
- });
+ mActionClickedListener = listener;
}
@Override
diff --git a/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlSupportGlue.java b/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlSupportGlue.java
index 48ca7f3..55ce89e 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlSupportGlue.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/PlaybackControlSupportGlue.java
@@ -7,6 +7,7 @@
import android.support.v17.leanback.widget.Action;
import android.support.v17.leanback.widget.OnActionClickedListener;
import android.support.v17.leanback.widget.OnItemViewClickedListener;
+import android.support.v17.leanback.widget.PlaybackRowPresenter;
import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.Row;
import android.support.v17.leanback.widget.RowPresenter;
@@ -138,10 +139,25 @@
static final class PlaybackSupportGlueHostOld extends PlaybackGlueHost {
final PlaybackOverlaySupportFragment mFragment;
- PlaybackControlGlue mGlue;
+ PlaybackControlSupportGlue mGlue;
+ OnActionClickedListener mActionClickedListener;
public PlaybackSupportGlueHostOld(PlaybackOverlaySupportFragment fragment) {
mFragment = fragment;
+ mFragment.setOnItemViewClickedListener(new OnItemViewClickedListener() {
+ @Override
+ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ if (item instanceof Action
+ && rowViewHolder instanceof PlaybackRowPresenter.ViewHolder
+ && mActionClickedListener != null) {
+ mActionClickedListener.onActionClicked((Action) item);
+ } else if (mGlue != null && mGlue.getOnItemViewClickedListener() != null) {
+ mGlue.getOnItemViewClickedListener().onItemClicked(itemViewHolder,
+ item, rowViewHolder, row);
+ }
+ }
+ });
}
@Override
@@ -165,19 +181,7 @@
@Override
public void setOnActionClickedListener(final OnActionClickedListener listener) {
- mFragment.setOnItemViewClickedListener(new OnItemViewClickedListener() {
- @Override
- public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
- RowPresenter.ViewHolder rowViewHolder, Row row) {
- if (item instanceof Action) {
- listener.onActionClicked((Action)item);
- if (mGlue.mExternalOnItemViewClickedListener != null) {
- mGlue.mExternalOnItemViewClickedListener.onItemClicked(itemViewHolder,
- item, rowViewHolder, row);
- }
- }
- }
- });
+ mActionClickedListener = listener;
}
@Override
diff --git a/v17/leanback/src/android/support/v17/leanback/app/PlaybackFragmentGlueHost.java b/v17/leanback/src/android/support/v17/leanback/app/PlaybackFragmentGlueHost.java
index d0acced..fdaa6ef 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/PlaybackFragmentGlueHost.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/PlaybackFragmentGlueHost.java
@@ -46,15 +46,19 @@
@Override
public void setOnActionClickedListener(final OnActionClickedListener listener) {
- mFragment.setOnPlaybackItemViewClickedListener(new OnItemViewClickedListener() {
- @Override
- public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
- RowPresenter.ViewHolder rowViewHolder, Row row) {
- if (item instanceof Action) {
- listener.onActionClicked((Action)item);
+ if (listener == null) {
+ mFragment.setOnPlaybackItemViewClickedListener(null);
+ } else {
+ mFragment.setOnPlaybackItemViewClickedListener(new OnItemViewClickedListener() {
+ @Override
+ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ if (item instanceof Action) {
+ listener.onActionClicked((Action) item);
+ }
}
- }
- });
+ });
+ }
}
@Override
diff --git a/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragmentGlueHost.java b/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragmentGlueHost.java
index 145bcbd..da644ae 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragmentGlueHost.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragmentGlueHost.java
@@ -49,15 +49,19 @@
@Override
public void setOnActionClickedListener(final OnActionClickedListener listener) {
- mFragment.setOnPlaybackItemViewClickedListener(new OnItemViewClickedListener() {
- @Override
- public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
- RowPresenter.ViewHolder rowViewHolder, Row row) {
- if (item instanceof Action) {
- listener.onActionClicked((Action)item);
+ if (listener == null) {
+ mFragment.setOnPlaybackItemViewClickedListener(null);
+ } else {
+ mFragment.setOnPlaybackItemViewClickedListener(new OnItemViewClickedListener() {
+ @Override
+ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ if (item instanceof Action) {
+ listener.onActionClicked((Action) item);
+ }
}
- }
- });
+ });
+ }
}
@Override
diff --git a/v17/leanback/src/android/support/v17/leanback/media/PlaybackControlGlue.java b/v17/leanback/src/android/support/v17/leanback/media/PlaybackControlGlue.java
index 6402fc6..bdd67fb 100644
--- a/v17/leanback/src/android/support/v17/leanback/media/PlaybackControlGlue.java
+++ b/v17/leanback/src/android/support/v17/leanback/media/PlaybackControlGlue.java
@@ -335,6 +335,7 @@
// Add secondary actions
ArrayObjectAdapter secondaryActions = new ArrayObjectAdapter(
new ControlButtonPresenterSelector());
+ onCreateSecondaryActions(secondaryActions);
getControlsRow().setSecondaryActionsAdapter(secondaryActions);
updateControlsRow();
}
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackControlGlueTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackControlGlueTest.java
index 45b8802..f26c60c 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackControlGlueTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackControlGlueTest.java
@@ -19,20 +19,29 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
+import android.support.v17.leanback.widget.OnItemViewClickedListener;
import android.support.v17.leanback.widget.PlaybackControlsRow;
+import android.support.v17.leanback.widget.PlaybackRowPresenter;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.RowPresenter;
import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
import android.view.KeyEvent;
+import android.view.View;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
@RunWith(AndroidJUnit4.class)
@MediumTest
@@ -502,4 +511,50 @@
assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
}
+ @Test
+ public void testOnItemClickedListener() {
+ PlaybackControlsRow row = new PlaybackControlsRow();
+ final PlaybackOverlayFragment[] fragmentResult = new PlaybackOverlayFragment[1];
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ fragmentResult[0] = new PlaybackOverlayFragment();
+ }
+ });
+ PlaybackOverlayFragment fragment = fragmentResult[0];
+ glue.setHost(new PlaybackControlGlue.PlaybackGlueHostOld(fragment));
+ glue.setControlsRow(row);
+ SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
+ row.getPrimaryActionsAdapter();
+ PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
+ .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
+ OnItemViewClickedListener listener = Mockito.mock(OnItemViewClickedListener.class);
+ glue.setOnItemViewClickedListener(listener);
+
+ // create fake row ViewHolder and fade item ViewHolder
+ View rowView = new View(context);
+ View view = new View(context);
+ PlaybackRowPresenter.ViewHolder rowVh = new PlaybackRowPresenter.ViewHolder(rowView);
+ Presenter.ViewHolder vh = new Presenter.ViewHolder(view);
+
+ // Initially media is paused
+ assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_PAUSED, glue.getCurrentSpeedId());
+
+ // simulate a click inside PlaybackOverlayFragment's PlaybackRow.
+ fragment.getOnItemViewClickedListener().onItemClicked(vh, playPause, rowVh, row);
+ verify(listener, times(0)).onItemClicked(vh, playPause, rowVh, row);
+ assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
+
+ // simulate a click on object other than PlaybackRow.
+ Object regularItem = new Object();
+ Row regularRow = new Row();
+ RowPresenter.ViewHolder regularRowViewHolder = new RowPresenter.ViewHolder(rowView);
+ Presenter.ViewHolder regularViewHOlder = new Presenter.ViewHolder(view);
+ fragment.getOnItemViewClickedListener().onItemClicked(regularViewHOlder, regularItem,
+ regularRowViewHolder, regularRow);
+ verify(listener, times(1)).onItemClicked(regularViewHOlder, regularItem,
+ regularRowViewHolder, regularRow);
+ assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
+ }
+
}
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackControlSupportGlueTest.java b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackControlSupportGlueTest.java
index d3e3271..211b42c 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackControlSupportGlueTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/app/PlaybackControlSupportGlueTest.java
@@ -22,20 +22,29 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
+import android.support.v17.leanback.widget.OnItemViewClickedListener;
import android.support.v17.leanback.widget.PlaybackControlsRow;
+import android.support.v17.leanback.widget.PlaybackRowPresenter;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.RowPresenter;
import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
import android.view.KeyEvent;
+import android.view.View;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
@RunWith(AndroidJUnit4.class)
@MediumTest
@@ -505,4 +514,50 @@
assertEquals(PlaybackControlSupportGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
}
+ @Test
+ public void testOnItemClickedListener() {
+ PlaybackControlsRow row = new PlaybackControlsRow();
+ final PlaybackOverlayFragment[] fragmentResult = new PlaybackOverlayFragment[1];
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ fragmentResult[0] = new PlaybackOverlayFragment();
+ }
+ });
+ PlaybackOverlayFragment fragment = fragmentResult[0];
+ glue.setHost(new PlaybackControlSupportGlue.PlaybackGlueHostOld(fragment));
+ glue.setControlsRow(row);
+ SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
+ row.getPrimaryActionsAdapter();
+ PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
+ .lookup(PlaybackControlSupportGlue.ACTION_PLAY_PAUSE);
+ OnItemViewClickedListener listener = Mockito.mock(OnItemViewClickedListener.class);
+ glue.setOnItemViewClickedListener(listener);
+
+ // create fake row ViewHolder and fade item ViewHolder
+ View rowView = new View(context);
+ View view = new View(context);
+ PlaybackRowPresenter.ViewHolder rowVh = new PlaybackRowPresenter.ViewHolder(rowView);
+ Presenter.ViewHolder vh = new Presenter.ViewHolder(view);
+
+ // Initially media is paused
+ assertEquals(PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED, glue.getCurrentSpeedId());
+
+ // simulate a click inside PlaybackOverlayFragment's PlaybackRow.
+ fragment.getOnItemViewClickedListener().onItemClicked(vh, playPause, rowVh, row);
+ verify(listener, times(0)).onItemClicked(vh, playPause, rowVh, row);
+ assertEquals(PlaybackControlSupportGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
+
+ // simulate a click on object other than PlaybackRow.
+ Object regularItem = new Object();
+ Row regularRow = new Row();
+ RowPresenter.ViewHolder regularRowViewHolder = new RowPresenter.ViewHolder(rowView);
+ Presenter.ViewHolder regularViewHOlder = new Presenter.ViewHolder(view);
+ fragment.getOnItemViewClickedListener().onItemClicked(regularViewHOlder, regularItem,
+ regularRowViewHolder, regularRow);
+ verify(listener, times(1)).onItemClicked(regularViewHOlder, regularItem,
+ regularRowViewHolder, regularRow);
+ assertEquals(PlaybackControlSupportGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
+ }
+
}