Fix some PlayerControlView accessibility issues
- Fix focus when pausing and resuming - Prevent repeated readout of the playback position when paused #exofixit #minor-release Issue #9111 PiperOrigin-RevId: 395301765
This commit is contained in:
parent
e53e59388f
commit
86f8c4e44e
@ -37,6 +37,8 @@
|
|||||||
* Use `defStyleAttr` when obtaining styled attributes in
|
* Use `defStyleAttr` when obtaining styled attributes in
|
||||||
`StyledPlayerView`, `PlayerView` and `PlayerControlView`
|
`StyledPlayerView`, `PlayerView` and `PlayerControlView`
|
||||||
([#9024](https://github.com/google/ExoPlayer/issues/9024)).
|
([#9024](https://github.com/google/ExoPlayer/issues/9024)).
|
||||||
|
* Fix accessibility focus in `PlayerControlView`
|
||||||
|
([#9111](https://github.com/google/ExoPlayer/issues/9111)).
|
||||||
* Remove deprecated symbols:
|
* Remove deprecated symbols:
|
||||||
* Remove `Renderer.VIDEO_SCALING_MODE_*` constants. Use identically named
|
* Remove `Renderer.VIDEO_SCALING_MODE_*` constants. Use identically named
|
||||||
constants in `C` instead.
|
constants in `C` instead.
|
||||||
|
@ -512,6 +512,9 @@ public class DefaultTimeBar extends View implements TimeBar {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPosition(long position) {
|
public void setPosition(long position) {
|
||||||
|
if (this.position == position) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.position = position;
|
this.position = position;
|
||||||
setContentDescription(getProgressText());
|
setContentDescription(getProgressText());
|
||||||
update();
|
update();
|
||||||
@ -519,12 +522,18 @@ public class DefaultTimeBar extends View implements TimeBar {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBufferedPosition(long bufferedPosition) {
|
public void setBufferedPosition(long bufferedPosition) {
|
||||||
|
if (this.bufferedPosition == bufferedPosition) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.bufferedPosition = bufferedPosition;
|
this.bufferedPosition = bufferedPosition;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDuration(long duration) {
|
public void setDuration(long duration) {
|
||||||
|
if (this.duration == duration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.duration = duration;
|
this.duration = duration;
|
||||||
if (scrubbing && duration == C.TIME_UNSET) {
|
if (scrubbing && duration == C.TIME_UNSET) {
|
||||||
stopScrubbing(/* canceled= */ true);
|
stopScrubbing(/* canceled= */ true);
|
||||||
|
@ -41,10 +41,13 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.accessibility.AccessibilityEvent;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import androidx.annotation.DoNotInline;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ControlDispatcher;
|
import com.google.android.exoplayer2.ControlDispatcher;
|
||||||
import com.google.android.exoplayer2.ExoPlayer;
|
import com.google.android.exoplayer2.ExoPlayer;
|
||||||
@ -339,6 +342,8 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
private long[] extraAdGroupTimesMs;
|
private long[] extraAdGroupTimesMs;
|
||||||
private boolean[] extraPlayedAdGroups;
|
private boolean[] extraPlayedAdGroups;
|
||||||
private long currentWindowOffset;
|
private long currentWindowOffset;
|
||||||
|
private long currentPosition;
|
||||||
|
private long currentBufferedPosition;
|
||||||
|
|
||||||
public PlayerControlView(Context context) {
|
public PlayerControlView(Context context) {
|
||||||
this(context, /* attrs= */ null);
|
this(context, /* attrs= */ null);
|
||||||
@ -783,6 +788,7 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
updateAll();
|
updateAll();
|
||||||
requestPlayPauseFocus();
|
requestPlayPauseFocus();
|
||||||
|
requestPlayPauseAccessibilityFocus();
|
||||||
}
|
}
|
||||||
// Call hideAfterTimeout even if already visible to reset the timeout.
|
// Call hideAfterTimeout even if already visible to reset the timeout.
|
||||||
hideAfterTimeout();
|
hideAfterTimeout();
|
||||||
@ -831,18 +837,30 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean requestPlayPauseFocus = false;
|
boolean requestPlayPauseFocus = false;
|
||||||
|
boolean requestPlayPauseAccessibilityFocus = false;
|
||||||
boolean shouldShowPauseButton = shouldShowPauseButton();
|
boolean shouldShowPauseButton = shouldShowPauseButton();
|
||||||
if (playButton != null) {
|
if (playButton != null) {
|
||||||
requestPlayPauseFocus |= shouldShowPauseButton && playButton.isFocused();
|
requestPlayPauseFocus |= shouldShowPauseButton && playButton.isFocused();
|
||||||
|
requestPlayPauseAccessibilityFocus |=
|
||||||
|
Util.SDK_INT < 21
|
||||||
|
? requestPlayPauseFocus
|
||||||
|
: (shouldShowPauseButton && Api21.isAccessibilityFocused(playButton));
|
||||||
playButton.setVisibility(shouldShowPauseButton ? GONE : VISIBLE);
|
playButton.setVisibility(shouldShowPauseButton ? GONE : VISIBLE);
|
||||||
}
|
}
|
||||||
if (pauseButton != null) {
|
if (pauseButton != null) {
|
||||||
requestPlayPauseFocus |= !shouldShowPauseButton && pauseButton.isFocused();
|
requestPlayPauseFocus |= !shouldShowPauseButton && pauseButton.isFocused();
|
||||||
|
requestPlayPauseAccessibilityFocus |=
|
||||||
|
Util.SDK_INT < 21
|
||||||
|
? requestPlayPauseFocus
|
||||||
|
: (!shouldShowPauseButton && Api21.isAccessibilityFocused(pauseButton));
|
||||||
pauseButton.setVisibility(shouldShowPauseButton ? VISIBLE : GONE);
|
pauseButton.setVisibility(shouldShowPauseButton ? VISIBLE : GONE);
|
||||||
}
|
}
|
||||||
if (requestPlayPauseFocus) {
|
if (requestPlayPauseFocus) {
|
||||||
requestPlayPauseFocus();
|
requestPlayPauseFocus();
|
||||||
}
|
}
|
||||||
|
if (requestPlayPauseAccessibilityFocus) {
|
||||||
|
requestPlayPauseAccessibilityFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateNavigation() {
|
private void updateNavigation() {
|
||||||
@ -1021,14 +1039,21 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
position = currentWindowOffset + player.getContentPosition();
|
position = currentWindowOffset + player.getContentPosition();
|
||||||
bufferedPosition = currentWindowOffset + player.getContentBufferedPosition();
|
bufferedPosition = currentWindowOffset + player.getContentBufferedPosition();
|
||||||
}
|
}
|
||||||
if (positionView != null && !scrubbing) {
|
boolean positionChanged = position != currentPosition;
|
||||||
|
boolean bufferedPositionChanged = bufferedPosition != currentBufferedPosition;
|
||||||
|
currentPosition = position;
|
||||||
|
currentBufferedPosition = bufferedPosition;
|
||||||
|
|
||||||
|
// Only update the TextView if the position has changed, else TalkBack will repeatedly read the
|
||||||
|
// same position to the user.
|
||||||
|
if (positionView != null && !scrubbing && positionChanged) {
|
||||||
positionView.setText(Util.getStringForTime(formatBuilder, formatter, position));
|
positionView.setText(Util.getStringForTime(formatBuilder, formatter, position));
|
||||||
}
|
}
|
||||||
if (timeBar != null) {
|
if (timeBar != null) {
|
||||||
timeBar.setPosition(position);
|
timeBar.setPosition(position);
|
||||||
timeBar.setBufferedPosition(bufferedPosition);
|
timeBar.setBufferedPosition(bufferedPosition);
|
||||||
}
|
}
|
||||||
if (progressUpdateListener != null) {
|
if (progressUpdateListener != null && (positionChanged || bufferedPositionChanged)) {
|
||||||
progressUpdateListener.onProgressUpdate(position, bufferedPosition);
|
progressUpdateListener.onProgressUpdate(position, bufferedPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1065,6 +1090,15 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void requestPlayPauseAccessibilityFocus() {
|
||||||
|
boolean shouldShowPauseButton = shouldShowPauseButton();
|
||||||
|
if (!shouldShowPauseButton && playButton != null) {
|
||||||
|
playButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
|
||||||
|
} else if (shouldShowPauseButton && pauseButton != null) {
|
||||||
|
pauseButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateButton(boolean visible, boolean enabled, @Nullable View view) {
|
private void updateButton(boolean visible, boolean enabled, @Nullable View view) {
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
return;
|
return;
|
||||||
@ -1339,4 +1373,12 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(21)
|
||||||
|
private static final class Api21 {
|
||||||
|
@DoNotInline
|
||||||
|
public static boolean isAccessibilityFocused(View view) {
|
||||||
|
return view.isAccessibilityFocused();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user