Merge pull request #10199 from TeamNewPipe/feat/player/accessibility

Improved accessibility of player interfaces
This commit is contained in:
Tobi 2023-09-21 15:57:38 +02:00 committed by GitHub
commit e2de83188a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 86 additions and 34 deletions

View file

@ -16,6 +16,7 @@ import android.view.MenuItem;
import android.view.SubMenu; import android.view.SubMenu;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.SeekBar; import android.widget.SeekBar;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -531,18 +532,19 @@ public final class PlayQueueActivity extends AppCompatActivity
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
private void onStateChanged(final int state) { private void onStateChanged(final int state) {
final ImageButton playPauseButton = queueControlBinding.controlPlayPause;
switch (state) { switch (state) {
case Player.STATE_PAUSED: case Player.STATE_PAUSED:
queueControlBinding.controlPlayPause playPauseButton.setImageResource(R.drawable.ic_play_arrow);
.setImageResource(R.drawable.ic_play_arrow); playPauseButton.setContentDescription(getString(R.string.play));
break; break;
case Player.STATE_PLAYING: case Player.STATE_PLAYING:
queueControlBinding.controlPlayPause playPauseButton.setImageResource(R.drawable.ic_pause);
.setImageResource(R.drawable.ic_pause); playPauseButton.setContentDescription(getString(R.string.pause));
break; break;
case Player.STATE_COMPLETED: case Player.STATE_COMPLETED:
queueControlBinding.controlPlayPause playPauseButton.setImageResource(R.drawable.ic_replay);
.setImageResource(R.drawable.ic_replay); playPauseButton.setContentDescription(getString(R.string.replay));
break; break;
default: default:
break; break;

View file

@ -41,6 +41,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.view.ContextThemeWrapper; import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.AppCompatImageButton;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.core.graphics.BitmapCompat; import androidx.core.graphics.BitmapCompat;
import androidx.core.graphics.Insets; import androidx.core.graphics.Insets;
@ -103,6 +104,9 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
// other constants (TODO remove playback speeds and use normal menu for popup, too) // other constants (TODO remove playback speeds and use normal menu for popup, too)
private static final float[] PLAYBACK_SPEEDS = {0.5f, 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f}; private static final float[] PLAYBACK_SPEEDS = {0.5f, 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f};
private enum PlayButtonAction {
PLAY, PAUSE, REPLAY
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Views // Views
@ -755,6 +759,29 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
// only MainPlayerUi can be in fullscreen, so overridden there // only MainPlayerUi can be in fullscreen, so overridden there
return false; return false;
} }
/**
* Update the play/pause button ({@link R.id.playPauseButton}) to reflect the action
* that will be performed when the button is clicked..
* @param action the action that is performed when the play/pause button is clicked
*/
private void updatePlayPauseButton(final PlayButtonAction action) {
final AppCompatImageButton button = binding.playPauseButton;
switch (action) {
case PLAY:
button.setContentDescription(context.getString(R.string.play));
button.setImageResource(R.drawable.ic_play_arrow);
break;
case PAUSE:
button.setContentDescription(context.getString(R.string.pause));
button.setImageResource(R.drawable.ic_pause);
break;
case REPLAY:
button.setContentDescription(context.getString(R.string.replay));
button.setImageResource(R.drawable.ic_replay);
break;
}
}
//endregion //endregion
@ -785,7 +812,7 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
animate(binding.loadingPanel, true, 0); animate(binding.loadingPanel, true, 0);
animate(binding.surfaceForeground, true, 100); animate(binding.surfaceForeground, true, 100);
binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow); updatePlayPauseButton(PlayButtonAction.PLAY);
animatePlayButtons(false, 100); animatePlayButtons(false, 100);
binding.getRoot().setKeepScreenOn(false); binding.getRoot().setKeepScreenOn(false);
} }
@ -806,7 +833,7 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
animate(binding.playPauseButton, false, 80, AnimationType.SCALE_AND_ALPHA, 0, animate(binding.playPauseButton, false, 80, AnimationType.SCALE_AND_ALPHA, 0,
() -> { () -> {
binding.playPauseButton.setImageResource(R.drawable.ic_pause); updatePlayPauseButton(PlayButtonAction.PAUSE);
animatePlayButtons(true, 200); animatePlayButtons(true, 200);
if (!isAnyListViewOpen()) { if (!isAnyListViewOpen()) {
binding.playPauseButton.requestFocus(); binding.playPauseButton.requestFocus();
@ -836,7 +863,7 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
animate(binding.playPauseButton, false, 80, AnimationType.SCALE_AND_ALPHA, 0, animate(binding.playPauseButton, false, 80, AnimationType.SCALE_AND_ALPHA, 0,
() -> { () -> {
binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow); updatePlayPauseButton(PlayButtonAction.PLAY);
animatePlayButtons(true, 200); animatePlayButtons(true, 200);
if (!isAnyListViewOpen()) { if (!isAnyListViewOpen()) {
binding.playPauseButton.requestFocus(); binding.playPauseButton.requestFocus();
@ -860,7 +887,7 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
animate(binding.playPauseButton, false, 0, AnimationType.SCALE_AND_ALPHA, 0, animate(binding.playPauseButton, false, 0, AnimationType.SCALE_AND_ALPHA, 0,
() -> { () -> {
binding.playPauseButton.setImageResource(R.drawable.ic_replay); updatePlayPauseButton(PlayButtonAction.REPLAY);
animatePlayButtons(true, DEFAULT_CONTROLS_DURATION); animatePlayButtons(true, DEFAULT_CONTROLS_DURATION);
}); });

View file

@ -123,7 +123,7 @@
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/exo_controls_rewind" android:src="@drawable/exo_controls_rewind"
android:tint="?attr/colorAccent" android:tint="?attr/colorAccent"
tools:ignore="ContentDescription" /> android:contentDescription="@string/rewind" />
<ImageButton <ImageButton
android:id="@+id/control_play_pause" android:id="@+id/control_play_pause"
@ -140,7 +140,7 @@
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/ic_pause" android:src="@drawable/ic_pause"
android:tint="?attr/colorAccent" android:tint="?attr/colorAccent"
tools:ignore="ContentDescription" /> android:contentDescription="@string/pause" />
<ProgressBar <ProgressBar
android:id="@+id/control_progress_bar" android:id="@+id/control_progress_bar"
@ -173,7 +173,7 @@
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/exo_controls_fastforward" android:src="@drawable/exo_controls_fastforward"
android:tint="?attr/colorAccent" android:tint="?attr/colorAccent"
tools:ignore="ContentDescription" /> android:contentDescription="@string/forward" />
</RelativeLayout> </RelativeLayout>
<RelativeLayout <RelativeLayout
@ -201,7 +201,7 @@
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/ic_previous" android:src="@drawable/ic_previous"
android:tint="?attr/colorAccent" android:tint="?attr/colorAccent"
tools:ignore="ContentDescription" /> android:contentDescription="@string/previous_stream" />
<ImageButton <ImageButton
android:id="@+id/control_repeat" android:id="@+id/control_repeat"
@ -216,7 +216,7 @@
android:scaleType="fitXY" android:scaleType="fitXY"
android:src="@drawable/ic_repeat" android:src="@drawable/ic_repeat"
android:tint="?attr/colorAccent" android:tint="?attr/colorAccent"
tools:ignore="ContentDescription" /> android:contentDescription="@string/notification_action_repeat" />
<View <View
android:id="@+id/anchor" android:id="@+id/anchor"
@ -237,7 +237,7 @@
android:scaleType="fitXY" android:scaleType="fitXY"
android:src="@drawable/ic_shuffle" android:src="@drawable/ic_shuffle"
android:tint="?attr/colorAccent" android:tint="?attr/colorAccent"
tools:ignore="ContentDescription" /> android:contentDescription="@string/notification_action_shuffle" />
<androidx.appcompat.widget.AppCompatImageButton <androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/control_forward" android:id="@+id/control_forward"
@ -255,7 +255,7 @@
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/ic_next" android:src="@drawable/ic_next"
android:tint="?attr/colorAccent" android:tint="?attr/colorAccent"
tools:ignore="ContentDescription" /> android:contentDescription="@string/next_stream" />
</RelativeLayout> </RelativeLayout>
</RelativeLayout> </RelativeLayout>

View file

@ -614,7 +614,8 @@
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingLeft="@dimen/video_item_search_padding" android:paddingLeft="@dimen/video_item_search_padding"
android:paddingRight="@dimen/video_item_search_padding" android:paddingRight="@dimen/video_item_search_padding"
android:scaleType="fitCenter" /> android:scaleType="fitCenter"
tools:ignore="ContentDescription" />
<LinearLayout <LinearLayout
android:id="@+id/overlay_metadata_layout" android:id="@+id/overlay_metadata_layout"
@ -675,7 +676,7 @@
android:contentDescription="@string/title_activity_play_queue" android:contentDescription="@string/title_activity_play_queue"
android:scaleType="center" android:scaleType="center"
android:src="@drawable/ic_list" android:src="@drawable/ic_list"
tools:ignore="ContentDescription,RtlHardcoded" /> tools:ignore="RtlHardcoded" />
<ImageButton <ImageButton
android:id="@+id/overlay_play_pause_button" android:id="@+id/overlay_play_pause_button"

View file

@ -39,6 +39,7 @@
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/duration_text_color" android:textColor="@color/duration_text_color"
android:textSize="@dimen/video_item_search_duration_text_size" android:textSize="@dimen/video_item_search_duration_text_size"
android:contentDescription="@string/duration"
app:layout_constraintBottom_toBottomOf="@+id/itemThumbnailView" app:layout_constraintBottom_toBottomOf="@+id/itemThumbnailView"
app:layout_constraintEnd_toEndOf="@+id/itemThumbnailView" app:layout_constraintEnd_toEndOf="@+id/itemThumbnailView"
tools:text="1:09:10" /> tools:text="1:09:10" />

View file

@ -115,7 +115,8 @@
android:src="@drawable/ic_close" android:src="@drawable/ic_close"
android:visibility="gone" android:visibility="gone"
app:tint="@color/white" app:tint="@color/white"
tools:ignore="ContentDescription,RtlHardcoded" /> android:contentDescription="@string/close"
tools:ignore="RtlHardcoded" />
<LinearLayout <LinearLayout
android:id="@+id/metadataView" android:id="@+id/metadataView"
@ -217,7 +218,8 @@
android:src="@drawable/ic_list" android:src="@drawable/ic_list"
android:visibility="gone" android:visibility="gone"
app:tint="@color/white" app:tint="@color/white"
tools:ignore="ContentDescription,RtlHardcoded" /> android:contentDescription="@string/open_play_queue"
tools:ignore="RtlHardcoded" />
<androidx.appcompat.widget.AppCompatImageButton <androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/segmentsButton" android:id="@+id/segmentsButton"
@ -235,7 +237,8 @@
android:src="@drawable/ic_menu_book" android:src="@drawable/ic_menu_book"
android:visibility="gone" android:visibility="gone"
app:tint="@color/white" app:tint="@color/white"
tools:ignore="ContentDescription,RtlHardcoded" /> android:contentDescription="@string/chapters"
tools:ignore="RtlHardcoded" />
<androidx.appcompat.widget.AppCompatImageButton <androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/moreOptionsButton" android:id="@+id/moreOptionsButton"
@ -248,7 +251,8 @@
android:scaleType="fitXY" android:scaleType="fitXY"
android:src="@drawable/ic_expand_more" android:src="@drawable/ic_expand_more"
app:tint="@color/white" app:tint="@color/white"
tools:ignore="ContentDescription,RtlHardcoded" /> android:contentDescription="@string/more_options"
tools:ignore="RtlHardcoded" />
</LinearLayout> </LinearLayout>
@ -368,9 +372,10 @@
android:padding="@dimen/player_main_buttons_padding" android:padding="@dimen/player_main_buttons_padding"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/ic_fullscreen" android:src="@drawable/ic_fullscreen"
android:contentDescription="@string/toggle_fullscreen"
android:visibility="gone" android:visibility="gone"
app:tint="@color/white" app:tint="@color/white"
tools:ignore="ContentDescription,RtlHardcoded" tools:ignore="RtlHardcoded"
tools:visibility="visible" /> tools:visibility="visible" />
</LinearLayout> </LinearLayout>
@ -493,8 +498,9 @@
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/ic_fullscreen" android:src="@drawable/ic_fullscreen"
android:visibility="gone" android:visibility="gone"
android:contentDescription="@string/toggle_screen_orientation"
app:tint="@color/white" app:tint="@color/white"
tools:ignore="ContentDescription,RtlHardcoded" tools:ignore="RtlHardcoded"
tools:visibility="visible" /> tools:visibility="visible" />
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>
@ -517,8 +523,8 @@
android:focusable="true" android:focusable="true"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/ic_previous" android:src="@drawable/ic_previous"
app:tint="@color/white" android:contentDescription="@string/previous_stream"
tools:ignore="ContentDescription" /> app:tint="@color/white" />
<androidx.appcompat.widget.AppCompatImageButton <androidx.appcompat.widget.AppCompatImageButton
@ -529,8 +535,8 @@
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/ic_pause" android:src="@drawable/ic_pause"
app:tint="@color/white" android:contentDescription="@string/pause"
tools:ignore="ContentDescription" /> app:tint="@color/white" />
<androidx.appcompat.widget.AppCompatImageButton <androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/playNextButton" android:id="@+id/playNextButton"
@ -543,8 +549,8 @@
android:focusable="true" android:focusable="true"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:src="@drawable/ic_next" android:src="@drawable/ic_next"
app:tint="@color/white" android:contentDescription="@string/next_stream"
tools:ignore="ContentDescription" /> app:tint="@color/white" />
</LinearLayout> </LinearLayout>
@ -595,7 +601,8 @@
android:scaleType="fitXY" android:scaleType="fitXY"
android:src="@drawable/exo_controls_repeat_off" android:src="@drawable/exo_controls_repeat_off"
android:tint="?attr/colorAccent" android:tint="?attr/colorAccent"
tools:ignore="ContentDescription,RtlHardcoded" /> android:contentDescription="@string/notification_action_repeat"
tools:ignore="RtlHardcoded" />
<androidx.appcompat.widget.AppCompatImageButton <androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/shuffleButton" android:id="@+id/shuffleButton"
@ -610,7 +617,8 @@
android:scaleType="fitXY" android:scaleType="fitXY"
android:src="@drawable/ic_shuffle" android:src="@drawable/ic_shuffle"
android:tint="?attr/colorAccent" android:tint="?attr/colorAccent"
tools:ignore="ContentDescription,RtlHardcoded" /> android:contentDescription="@string/notification_action_shuffle"
tools:ignore="RtlHardcoded" />
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
android:id="@+id/itemsListHeaderDuration" android:id="@+id/itemsListHeaderDuration"
@ -636,7 +644,8 @@
android:scaleType="fitXY" android:scaleType="fitXY"
android:src="@drawable/ic_playlist_add" android:src="@drawable/ic_playlist_add"
android:tint="?attr/colorAccent" android:tint="?attr/colorAccent"
tools:ignore="ContentDescription,RtlHardcoded" /> android:contentDescription="@string/add_to_playlist"
tools:ignore="RtlHardcoded" />
<androidx.appcompat.widget.AppCompatImageButton <androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/itemsListClose" android:id="@+id/itemsListClose"

View file

@ -11,6 +11,7 @@
android:layout_gravity="bottom|center_horizontal" android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="24dp" android:layout_marginBottom="24dp"
android:src="@drawable/ic_close" android:src="@drawable/ic_close"
android:contentDescription="@string/close"
app:backgroundTint="@color/light_youtube_primary_color" app:backgroundTint="@color/light_youtube_primary_color"
app:borderWidth="0dp" app:borderWidth="0dp"
app:fabSize="normal" /> app:fabSize="normal" />

View file

@ -811,4 +811,15 @@
<string name="channel_tab_about">About</string> <string name="channel_tab_about">About</string>
<string name="show_channel_tabs">Channel tabs</string> <string name="show_channel_tabs">Channel tabs</string>
<string name="show_channel_tabs_summary">What tabs are shown on the channel pages</string> <string name="show_channel_tabs_summary">What tabs are shown on the channel pages</string>
<string name="open_play_queue">Open play queue</string>
<string name="toggle_fullscreen">Toggle fullscreen</string>
<string name="toggle_screen_orientation">Toggle screen orientation</string>
<string name="previous_stream">Previous stream</string>
<string name="next_stream">Next stream</string>
<string name="play">Play</string>
<string name="replay">Replay</string>
<string name="more_options">More options</string>
<string name="duration">Duration</string>
<string name="rewind">Rewind</string>
<string name="forward">Forward</string>
</resources> </resources>