Commit 195a93e5 by olly Committed by Oliver Woodman

Fix playback control focus

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=140623107
parent 8dc81040
...@@ -22,6 +22,7 @@ import android.net.Uri; ...@@ -22,6 +22,7 @@ import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.Button;
...@@ -194,6 +195,16 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay ...@@ -194,6 +195,16 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
} }
} }
// Activity input
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
// Show the controls on any key event.
simpleExoPlayerView.showController();
// If the event was not handled then see if the player view can handle it as a media key event.
return super.dispatchKeyEvent(event) || simpleExoPlayerView.dispatchMediaKeyEvent(event);
}
// OnClickListener methods // OnClickListener methods
@Override @Override
......
...@@ -16,13 +16,11 @@ ...@@ -16,13 +16,11 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root" android:id="@+id/root"
android:focusable="true"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:keepScreenOn="true"> android:keepScreenOn="true">
<com.google.android.exoplayer2.ui.SimpleExoPlayerView android:id="@+id/player_view" <com.google.android.exoplayer2.ui.SimpleExoPlayerView android:id="@+id/player_view"
android:focusable="true"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"/> android:layout_height="match_parent"/>
......
...@@ -236,6 +236,8 @@ public class PlaybackControlView extends FrameLayout { ...@@ -236,6 +236,8 @@ public class PlaybackControlView extends FrameLayout {
componentListener = new ComponentListener(); componentListener = new ComponentListener();
LayoutInflater.from(context).inflate(controllerLayoutId, this); LayoutInflater.from(context).inflate(controllerLayoutId, this);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
durationView = (TextView) findViewById(R.id.exo_duration); durationView = (TextView) findViewById(R.id.exo_duration);
positionView = (TextView) findViewById(R.id.exo_position); positionView = (TextView) findViewById(R.id.exo_position);
progressBar = (SeekBar) findViewById(R.id.exo_progress); progressBar = (SeekBar) findViewById(R.id.exo_progress);
...@@ -359,6 +361,7 @@ public class PlaybackControlView extends FrameLayout { ...@@ -359,6 +361,7 @@ public class PlaybackControlView extends FrameLayout {
visibilityListener.onVisibilityChange(getVisibility()); visibilityListener.onVisibilityChange(getVisibility());
} }
updateAll(); updateAll();
requestPlayPauseFocus();
} }
// Call hideAfterTimeout even if already visible to reset the timeout. // Call hideAfterTimeout even if already visible to reset the timeout.
hideAfterTimeout(); hideAfterTimeout();
...@@ -408,12 +411,18 @@ public class PlaybackControlView extends FrameLayout { ...@@ -408,12 +411,18 @@ public class PlaybackControlView extends FrameLayout {
if (!isVisible() || !isAttachedToWindow) { if (!isVisible() || !isAttachedToWindow) {
return; return;
} }
boolean requestPlayPauseFocus = false;
boolean playing = player != null && player.getPlayWhenReady(); boolean playing = player != null && player.getPlayWhenReady();
if (playButton != null) { if (playButton != null) {
playButton.setVisibility(playing ? GONE : VISIBLE); requestPlayPauseFocus |= playing && playButton.isFocused();
playButton.setVisibility(playing ? View.GONE : View.VISIBLE);
} }
if (pauseButton != null) { if (pauseButton != null) {
pauseButton.setVisibility(playing ? VISIBLE : GONE); requestPlayPauseFocus |= !playing && pauseButton.isFocused();
pauseButton.setVisibility(!playing ? View.GONE : View.VISIBLE);
}
if (requestPlayPauseFocus) {
requestPlayPauseFocus();
} }
} }
...@@ -481,6 +490,15 @@ public class PlaybackControlView extends FrameLayout { ...@@ -481,6 +490,15 @@ public class PlaybackControlView extends FrameLayout {
} }
} }
private void requestPlayPauseFocus() {
boolean playing = player != null && player.getPlayWhenReady();
if (!playing && playButton != null) {
playButton.requestFocus();
} else if (playing && pauseButton != null) {
pauseButton.requestFocus();
}
}
private void setButtonEnabled(boolean enabled, View view) { private void setButtonEnabled(boolean enabled, View view) {
if (view == null) { if (view == null) {
return; return;
...@@ -590,16 +608,31 @@ public class PlaybackControlView extends FrameLayout { ...@@ -590,16 +608,31 @@ public class PlaybackControlView extends FrameLayout {
@Override @Override
public boolean dispatchKeyEvent(KeyEvent event) { public boolean dispatchKeyEvent(KeyEvent event) {
if (player == null || event.getAction() != KeyEvent.ACTION_DOWN) { boolean handled = dispatchMediaKeyEvent(event) || super.dispatchKeyEvent(event);
return super.dispatchKeyEvent(event); if (handled) {
show();
}
return handled;
} }
switch (event.getKeyCode()) {
/**
* Called to process media key events. Any {@link KeyEvent} can be passed but only media key
* events will be handled.
*
* @param event A key event.
* @return Whether the key event was handled.
*/
public boolean dispatchMediaKeyEvent(KeyEvent event) {
int keyCode = event.getKeyCode();
if (player == null || !isHandledMediaKey(keyCode)) {
return false;
}
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
case KeyEvent.KEYCODE_DPAD_RIGHT:
fastForward(); fastForward();
break; break;
case KeyEvent.KEYCODE_MEDIA_REWIND: case KeyEvent.KEYCODE_MEDIA_REWIND:
case KeyEvent.KEYCODE_DPAD_LEFT:
rewind(); rewind();
break; break;
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
...@@ -618,12 +651,23 @@ public class PlaybackControlView extends FrameLayout { ...@@ -618,12 +651,23 @@ public class PlaybackControlView extends FrameLayout {
previous(); previous();
break; break;
default: default:
return false; break;
}
} }
show(); show();
return true; return true;
} }
private static boolean isHandledMediaKey(int keyCode) {
return keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD
|| keyCode == KeyEvent.KEYCODE_MEDIA_REWIND
|| keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
|| keyCode == KeyEvent.KEYCODE_MEDIA_PLAY
|| keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE
|| keyCode == KeyEvent.KEYCODE_MEDIA_NEXT
|| keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS;
}
private final class ComponentListener implements ExoPlayer.EventListener, private final class ComponentListener implements ExoPlayer.EventListener,
SeekBar.OnSeekBarChangeListener, OnClickListener { SeekBar.OnSeekBarChangeListener, OnClickListener {
......
...@@ -216,6 +216,7 @@ public final class SimpleExoPlayerView extends FrameLayout { ...@@ -216,6 +216,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
LayoutInflater.from(context).inflate(playerLayoutId, this); LayoutInflater.from(context).inflate(playerLayoutId, this);
componentListener = new ComponentListener(); componentListener = new ComponentListener();
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
// Content frame. // Content frame.
contentFrame = (AspectRatioFrameLayout) findViewById(R.id.exo_content_frame); contentFrame = (AspectRatioFrameLayout) findViewById(R.id.exo_content_frame);
...@@ -377,6 +378,26 @@ public final class SimpleExoPlayerView extends FrameLayout { ...@@ -377,6 +378,26 @@ public final class SimpleExoPlayerView extends FrameLayout {
} }
/** /**
* Called to process media key events. Any {@link KeyEvent} can be passed but only media key
* events will be handled. Does nothing if playback controls are disabled.
*
* @param event A key event.
* @return Whether the key event was handled.
*/
public boolean dispatchMediaKeyEvent(KeyEvent event) {
return useController && controller.dispatchMediaKeyEvent(event);
}
/**
* Shows the playback controls. Does nothing if playback controls are disabled.
*/
public void showController() {
if (useController) {
maybeShowController(true);
}
}
/**
* Returns the playback controls timeout. The playback controls are automatically hidden after * Returns the playback controls timeout. The playback controls are automatically hidden after
* this duration of time has elapsed without user input and with playback or buffering in * this duration of time has elapsed without user input and with playback or buffering in
* progress. * progress.
...@@ -473,11 +494,6 @@ public final class SimpleExoPlayerView extends FrameLayout { ...@@ -473,11 +494,6 @@ public final class SimpleExoPlayerView extends FrameLayout {
return true; return true;
} }
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
return useController ? controller.dispatchKeyEvent(event) : super.dispatchKeyEvent(event);
}
private void maybeShowController(boolean isForced) { private void maybeShowController(boolean isForced) {
if (!useController || player == null) { if (!useController || player == null) {
return; return;
......
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:layoutDirection="ltr"
android:background="#CC000000" android:background="#CC000000"
android:orientation="vertical" android:orientation="vertical">
android:layoutDirection="ltr">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1" android:layout_weight="1"
android:layout_height="32dp" android:layout_height="32dp"
android:focusable="false"
style="?android:attr/progressBarStyleHorizontal"/> style="?android:attr/progressBarStyleHorizontal"/>
<TextView android:id="@id/exo_duration" <TextView android:id="@id/exo_duration"
......
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
<style name="ExoMediaButton"> <style name="ExoMediaButton">
<item name="android:background">@null</item> <item name="android:background">@null</item>
<item name="android:layout_width">71dip</item> <item name="android:layout_width">71dp</item>
<item name="android:layout_height">52dip</item> <item name="android:layout_height">52dp</item>
</style> </style>
<style name="ExoMediaButton.Previous"> <style name="ExoMediaButton.Previous">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment