mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
provide content description for the player view to make show/hide controls accessible
PiperOrigin-RevId: 274148026
This commit is contained in:
parent
a268e1b63f
commit
674e92e1ee
4 changed files with 64 additions and 11 deletions
|
|
@ -110,6 +110,7 @@
|
||||||
* Add `MediaPeriod.isLoading` to improve `Player.isLoading` state.
|
* Add `MediaPeriod.isLoading` to improve `Player.isLoading` state.
|
||||||
* Add support for ID3-in-EMSG in HLS streams
|
* Add support for ID3-in-EMSG in HLS streams
|
||||||
([spec](https://aomediacodec.github.io/av1-id3/)).
|
([spec](https://aomediacodec.github.io/av1-id3/)).
|
||||||
|
* Make show and hide player controls accessible for TalkBack in `PlayerView`.
|
||||||
|
|
||||||
### 2.10.5 (2019-09-20) ###
|
### 2.10.5 (2019-09-20) ###
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Formatter;
|
import java.util.Formatter;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A view for controlling {@link Player} instances.
|
* A view for controlling {@link Player} instances.
|
||||||
|
|
@ -231,6 +232,7 @@ public class PlayerControlView extends FrameLayout {
|
||||||
private static final int MAX_UPDATE_INTERVAL_MS = 1000;
|
private static final int MAX_UPDATE_INTERVAL_MS = 1000;
|
||||||
|
|
||||||
private final ComponentListener componentListener;
|
private final ComponentListener componentListener;
|
||||||
|
private final CopyOnWriteArrayList<VisibilityListener> visibilityListeners;
|
||||||
private final View previousButton;
|
private final View previousButton;
|
||||||
private final View nextButton;
|
private final View nextButton;
|
||||||
private final View playButton;
|
private final View playButton;
|
||||||
|
|
@ -265,7 +267,6 @@ public class PlayerControlView extends FrameLayout {
|
||||||
|
|
||||||
@Nullable private Player player;
|
@Nullable private Player player;
|
||||||
private com.google.android.exoplayer2.ControlDispatcher controlDispatcher;
|
private com.google.android.exoplayer2.ControlDispatcher controlDispatcher;
|
||||||
@Nullable private VisibilityListener visibilityListener;
|
|
||||||
@Nullable private ProgressUpdateListener progressUpdateListener;
|
@Nullable private ProgressUpdateListener progressUpdateListener;
|
||||||
@Nullable private PlaybackPreparer playbackPreparer;
|
@Nullable private PlaybackPreparer playbackPreparer;
|
||||||
|
|
||||||
|
|
@ -335,6 +336,7 @@ public class PlayerControlView extends FrameLayout {
|
||||||
a.recycle();
|
a.recycle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
visibilityListeners = new CopyOnWriteArrayList<>();
|
||||||
period = new Timeline.Period();
|
period = new Timeline.Period();
|
||||||
window = new Timeline.Window();
|
window = new Timeline.Window();
|
||||||
formatBuilder = new StringBuilder();
|
formatBuilder = new StringBuilder();
|
||||||
|
|
@ -510,13 +512,21 @@ public class PlayerControlView extends FrameLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link VisibilityListener}.
|
* Adds a {@link VisibilityListener}.
|
||||||
*
|
*
|
||||||
* @param listener The listener to be notified about visibility changes, or null to remove the
|
* @param listener The listener to be notified about visibility changes.
|
||||||
* current listener.
|
|
||||||
*/
|
*/
|
||||||
public void setVisibilityListener(@Nullable VisibilityListener listener) {
|
public void addVisibilityListener(VisibilityListener listener) {
|
||||||
this.visibilityListener = listener;
|
visibilityListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a {@link VisibilityListener}.
|
||||||
|
*
|
||||||
|
* @param listener The listener to be removed.
|
||||||
|
*/
|
||||||
|
public void removeVisibilityListener(VisibilityListener listener) {
|
||||||
|
visibilityListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -697,7 +707,7 @@ public class PlayerControlView extends FrameLayout {
|
||||||
public void show() {
|
public void show() {
|
||||||
if (!isVisible()) {
|
if (!isVisible()) {
|
||||||
setVisibility(VISIBLE);
|
setVisibility(VISIBLE);
|
||||||
if (visibilityListener != null) {
|
for (VisibilityListener visibilityListener : visibilityListeners) {
|
||||||
visibilityListener.onVisibilityChange(getVisibility());
|
visibilityListener.onVisibilityChange(getVisibility());
|
||||||
}
|
}
|
||||||
updateAll();
|
updateAll();
|
||||||
|
|
@ -711,7 +721,7 @@ public class PlayerControlView extends FrameLayout {
|
||||||
public void hide() {
|
public void hide() {
|
||||||
if (isVisible()) {
|
if (isVisible()) {
|
||||||
setVisibility(GONE);
|
setVisibility(GONE);
|
||||||
if (visibilityListener != null) {
|
for (VisibilityListener visibilityListener : visibilityListeners) {
|
||||||
visibilityListener.onVisibilityChange(getVisibility());
|
visibilityListener.onVisibilityChange(getVisibility());
|
||||||
}
|
}
|
||||||
removeCallbacks(updateProgressAction);
|
removeCallbacks(updateProgressAction);
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
|
||||||
|
|
||||||
private Player player;
|
private Player player;
|
||||||
private boolean useController;
|
private boolean useController;
|
||||||
|
@Nullable private PlayerControlView.VisibilityListener controllerVisibilityListener;
|
||||||
private boolean useArtwork;
|
private boolean useArtwork;
|
||||||
@Nullable private Drawable defaultArtwork;
|
@Nullable private Drawable defaultArtwork;
|
||||||
private @ShowBuffering int showBuffering;
|
private @ShowBuffering int showBuffering;
|
||||||
|
|
@ -483,6 +484,10 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
|
||||||
this.controllerHideDuringAds = controllerHideDuringAds;
|
this.controllerHideDuringAds = controllerHideDuringAds;
|
||||||
this.useController = useController && controller != null;
|
this.useController = useController && controller != null;
|
||||||
hideController();
|
hideController();
|
||||||
|
updateContentDescription();
|
||||||
|
if (controller != null) {
|
||||||
|
controller.addVisibilityListener(/* listener= */ componentListener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -687,8 +692,9 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
|
||||||
controller.setPlayer(player);
|
controller.setPlayer(player);
|
||||||
} else if (controller != null) {
|
} else if (controller != null) {
|
||||||
controller.hide();
|
controller.hide();
|
||||||
controller.setPlayer(null);
|
controller.setPlayer(/* player= */ null);
|
||||||
}
|
}
|
||||||
|
updateContentDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -880,6 +886,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
|
||||||
public void setControllerHideOnTouch(boolean controllerHideOnTouch) {
|
public void setControllerHideOnTouch(boolean controllerHideOnTouch) {
|
||||||
Assertions.checkState(controller != null);
|
Assertions.checkState(controller != null);
|
||||||
this.controllerHideOnTouch = controllerHideOnTouch;
|
this.controllerHideOnTouch = controllerHideOnTouch;
|
||||||
|
updateContentDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -921,7 +928,16 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
|
||||||
public void setControllerVisibilityListener(
|
public void setControllerVisibilityListener(
|
||||||
@Nullable PlayerControlView.VisibilityListener listener) {
|
@Nullable PlayerControlView.VisibilityListener listener) {
|
||||||
Assertions.checkState(controller != null);
|
Assertions.checkState(controller != null);
|
||||||
controller.setVisibilityListener(listener);
|
if (this.controllerVisibilityListener == listener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.controllerVisibilityListener != null) {
|
||||||
|
controller.removeVisibilityListener(this.controllerVisibilityListener);
|
||||||
|
}
|
||||||
|
this.controllerVisibilityListener = listener;
|
||||||
|
if (listener != null) {
|
||||||
|
controller.addVisibilityListener(listener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1359,6 +1375,20 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateContentDescription() {
|
||||||
|
if (controller == null || !useController) {
|
||||||
|
setContentDescription(/* contentDescription= */ null);
|
||||||
|
} else if (controller.getVisibility() == View.VISIBLE) {
|
||||||
|
setContentDescription(
|
||||||
|
/* contentDescription= */ controllerHideOnTouch
|
||||||
|
? getResources().getString(R.string.exo_controls_hide)
|
||||||
|
: null);
|
||||||
|
} else {
|
||||||
|
setContentDescription(
|
||||||
|
/* contentDescription= */ getResources().getString(R.string.exo_controls_show));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TargetApi(23)
|
@TargetApi(23)
|
||||||
private static void configureEditModeLogoV23(Resources resources, ImageView logo) {
|
private static void configureEditModeLogoV23(Resources resources, ImageView logo) {
|
||||||
logo.setImageDrawable(resources.getDrawable(R.drawable.exo_edit_mode_logo, null));
|
logo.setImageDrawable(resources.getDrawable(R.drawable.exo_edit_mode_logo, null));
|
||||||
|
|
@ -1418,7 +1448,8 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
|
||||||
TextOutput,
|
TextOutput,
|
||||||
VideoListener,
|
VideoListener,
|
||||||
OnLayoutChangeListener,
|
OnLayoutChangeListener,
|
||||||
SingleTapListener {
|
SingleTapListener,
|
||||||
|
PlayerControlView.VisibilityListener {
|
||||||
|
|
||||||
// TextOutput implementation
|
// TextOutput implementation
|
||||||
|
|
||||||
|
|
@ -1513,5 +1544,12 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
|
||||||
public boolean onSingleTapUp(MotionEvent e) {
|
public boolean onSingleTapUp(MotionEvent e) {
|
||||||
return toggleControllerVisibility();
|
return toggleControllerVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PlayerControlView.VisibilityListener implementation
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onVisibilityChange(int visibility) {
|
||||||
|
updateContentDescription();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<!-- Description for a media player view to indicate that tapping on the view shows the playback controls. [CHAR LIMIT=50] -->
|
||||||
|
<string name="exo_controls_show">Show player controls</string>
|
||||||
|
<!-- Description for a media player view to indicate that tapping on the view hides the playback controls [CHAR LIMIT=50] -->
|
||||||
|
<string name="exo_controls_hide">Hide player controls</string>
|
||||||
<!-- Description for a media control button that causes the previous track to be played. [CHAR LIMIT=30] -->
|
<!-- Description for a media control button that causes the previous track to be played. [CHAR LIMIT=30] -->
|
||||||
<string name="exo_controls_previous_description">Previous track</string>
|
<string name="exo_controls_previous_description">Previous track</string>
|
||||||
<!-- Description for a media control button that causes the next track to be played. [CHAR LIMIT=30] -->
|
<!-- Description for a media control button that causes the next track to be played. [CHAR LIMIT=30] -->
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue