Implemented the logic of podcast controllers

This commit is contained in:
CappielloAntonio 2022-02-08 17:46:13 +01:00
parent 072b339f8c
commit c376adf2d9
8 changed files with 295 additions and 12 deletions

8
.idea/misc.xml generated
View file

@ -18,6 +18,7 @@
<entry key="app/src/main/res/drawable/bottom_nav_shape.xml" value="0.28055555555555556" />
<entry key="app/src/main/res/drawable/button_favorite_selector.xml" value="0.46296296296296297" />
<entry key="app/src/main/res/drawable/button_play_pause_selector.xml" value="0.2722222222222222" />
<entry key="app/src/main/res/drawable/button_skip_silence_selector.xml" value="0.156" />
<entry key="app/src/main/res/drawable/dialog_shape.xml" value="0.27685185185185185" />
<entry key="app/src/main/res/drawable/gradient_discover_background_image.xml" value="0.28703703703703703" />
<entry key="app/src/main/res/drawable/gradient_player_cover_background_image.xml" value="0.3365679264555669" />
@ -34,6 +35,7 @@
<entry key="app/src/main/res/drawable/ic_favorites_outlined.xml" value="0.28055555555555556" />
<entry key="app/src/main/res/drawable/ic_feed.xml" value="0.28055555555555556" />
<entry key="app/src/main/res/drawable/ic_file_download.xml" value="0.2722222222222222" />
<entry key="app/src/main/res/drawable/ic_forward.xml" value="0.156" />
<entry key="app/src/main/res/drawable/ic_genre.xml" value="0.24814814814814815" />
<entry key="app/src/main/res/drawable/ic_grade.xml" value="0.28703703703703703" />
<entry key="app/src/main/res/drawable/ic_graphic_eq.xml" value="0.28055555555555556" />
@ -60,6 +62,7 @@
<entry key="app/src/main/res/drawable/ic_rating.xml" value="0.28703703703703703" />
<entry key="app/src/main/res/drawable/ic_refresh.xml" value="0.18958333333333333" />
<entry key="app/src/main/res/drawable/ic_repeat.xml" value="0.28703703703703703" />
<entry key="app/src/main/res/drawable/ic_replay.xml" value="0.156" />
<entry key="app/src/main/res/drawable/ic_search.xml" value="0.27685185185185185" />
<entry key="app/src/main/res/drawable/ic_settings.xml" value="0.28055555555555556" />
<entry key="app/src/main/res/drawable/ic_show_queue.xml" value="0.28703703703703703" />
@ -68,6 +71,9 @@
<entry key="app/src/main/res/drawable/ic_skip_next_white_24dp.xml" value="0.28055555555555556" />
<entry key="app/src/main/res/drawable/ic_skip_previous.xml" value="0.5484375" />
<entry key="app/src/main/res/drawable/ic_skip_previous_white_24dp.xml" value="0.28055555555555556" />
<entry key="app/src/main/res/drawable/ic_skip_silence.xml" value="0.156" />
<entry key="app/src/main/res/drawable/ic_skip_silence_outlined.xml" value="0.156" />
<entry key="app/src/main/res/drawable/ic_speed.xml" value="0.156" />
<entry key="app/src/main/res/drawable/ic_star.xml" value="0.2722222222222222" />
<entry key="app/src/main/res/drawable/ic_toolbar_motion_on.xml" value="0.30625" />
<entry key="app/src/main/res/drawable/ic_unfold.xml" value="0.5484375" />
@ -110,7 +116,7 @@
<entry key="app/src/main/res/layout/fragment_song_list_page.xml" value="0.225" />
<entry key="app/src/main/res/layout/fragment_starred.xml" value="0.3166496424923391" />
<entry key="app/src/main/res/layout/inner_fragment_player_controller.xml" value="0.3229166666666667" />
<entry key="app/src/main/res/layout/inner_fragment_player_controller_layout.xml" value="0.3229166666666667" />
<entry key="app/src/main/res/layout/inner_fragment_player_controller_layout.xml" value="0.6" />
<entry key="app/src/main/res/layout/inner_fragment_player_cover.xml" value="0.40390879478827363" />
<entry key="app/src/main/res/layout/inner_fragment_player_lyrics.xml" value="0.3229166666666667" />
<entry key="app/src/main/res/layout/inner_fragment_player_queue.xml" value="0.3229166666666667" />

View file

@ -16,6 +16,13 @@ public class Media implements Parcelable {
public static final String MEDIA_TYPE_AUDIOBOOK = "audiobook";
public static final String MEDIA_TYPE_VIDEO = "video";
public static final float MEDIA_PLAYBACK_SPEED_080 = 0.8f;
public static final float MEDIA_PLAYBACK_SPEED_100 = 1.0f;
public static final float MEDIA_PLAYBACK_SPEED_125 = 1.25f;
public static final float MEDIA_PLAYBACK_SPEED_150 = 1.50f;
public static final float MEDIA_PLAYBACK_SPEED_175 = 1.75f;
public static final float MEDIA_PLAYBACK_SPEED_200 = 2.0f;
public static final String RECENTLY_PLAYED = "RECENTLY_PLAYED";
public static final String MOST_PLAYED = "MOST_PLAYED";
public static final String RECENTLY_ADDED = "RECENTLY_ADDED";

View file

@ -14,6 +14,7 @@ import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.media3.common.MediaMetadata;
import androidx.media3.common.Player;
import androidx.media3.common.util.RepeatModeUtil;
import androidx.media3.session.MediaBrowser;
import androidx.media3.session.MediaController;
import androidx.media3.session.SessionToken;
@ -23,6 +24,7 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.databinding.FragmentPlayerBottomSheetBinding;
import com.cappielloantonio.play.glide.CustomGlideRequest;
import com.cappielloantonio.play.model.Media;
import com.cappielloantonio.play.service.MediaService;
import com.cappielloantonio.play.ui.fragment.pager.PlayerControllerVerticalPager;
import com.cappielloantonio.play.util.MusicUtil;
@ -108,6 +110,7 @@ public class PlayerBottomSheetFragment extends Fragment {
@SuppressLint("UnsafeOptInUsageError")
private void setMediaControllerListener(MediaBrowser mediaBrowser) {
setMediaControllerUI(mediaBrowser);
setMetadata(mediaBrowser.getMediaMetadata());
setContentDuration(mediaBrowser.getContentDuration());
setPlayingState(mediaBrowser.isPlaying());
@ -117,6 +120,7 @@ public class PlayerBottomSheetFragment extends Fragment {
mediaBrowser.addListener(new Player.Listener() {
@Override
public void onMediaMetadataChanged(@NonNull MediaMetadata mediaMetadata) {
setMediaControllerUI(mediaBrowser);
setMetadata(mediaMetadata);
setContentDuration(mediaBrowser.getContentDuration());
}
@ -150,6 +154,25 @@ public class PlayerBottomSheetFragment extends Fragment {
.into(bind.playerHeaderLayout.playerHeaderMediaCoverImage);
}
@SuppressLint("UnsafeOptInUsageError")
private void setMediaControllerUI(MediaBrowser mediaBrowser) {
if (mediaBrowser.getMediaMetadata().extras != null) {
switch (mediaBrowser.getMediaMetadata().extras.getString("mediaType", Media.MEDIA_TYPE_MUSIC)) {
case Media.MEDIA_TYPE_PODCAST:
bind.playerHeaderLayout.playerHeaderFastForwardMediaButton.setVisibility(View.VISIBLE);
bind.playerHeaderLayout.playerHeaderRewindMediaButton.setVisibility(View.VISIBLE);
bind.playerHeaderLayout.playerHeaderNextMediaButton.setVisibility(View.GONE);
break;
case Media.MEDIA_TYPE_MUSIC:
default:
bind.playerHeaderLayout.playerHeaderFastForwardMediaButton.setVisibility(View.GONE);
bind.playerHeaderLayout.playerHeaderRewindMediaButton.setVisibility(View.GONE);
bind.playerHeaderLayout.playerHeaderNextMediaButton.setVisibility(View.VISIBLE);
break;
}
}
}
private void setContentDuration(long duration) {
bind.playerHeaderLayout.playerHeaderSeekBar.setMax((int) (duration / 1000));
}
@ -169,6 +192,8 @@ public class PlayerBottomSheetFragment extends Fragment {
});
bind.playerHeaderLayout.playerHeaderNextMediaButton.setOnClickListener(view -> bind.getRoot().findViewById(R.id.exo_next).performClick());
bind.playerHeaderLayout.playerHeaderRewindMediaButton.setOnClickListener(view -> bind.getRoot().findViewById(R.id.exo_rew).performClick());
bind.playerHeaderLayout.playerHeaderFastForwardMediaButton.setOnClickListener(view -> bind.getRoot().findViewById(R.id.exo_ffwd).performClick());
}
private void setHeaderNextButtonState(boolean isEnabled) {

View file

@ -7,6 +7,7 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ToggleButton;
@ -15,7 +16,9 @@ import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.media3.common.MediaMetadata;
import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player;
import androidx.media3.common.util.RepeatModeUtil;
import androidx.media3.session.MediaBrowser;
import androidx.media3.session.SessionToken;
import androidx.navigation.fragment.NavHostFragment;
@ -23,11 +26,13 @@ import androidx.viewpager2.widget.ViewPager2;
import com.cappielloantonio.play.R;
import com.cappielloantonio.play.databinding.InnerFragmentPlayerControllerBinding;
import com.cappielloantonio.play.model.Media;
import com.cappielloantonio.play.service.MediaService;
import com.cappielloantonio.play.ui.activity.MainActivity;
import com.cappielloantonio.play.ui.dialog.RatingDialog;
import com.cappielloantonio.play.ui.fragment.pager.PlayerControllerHorizontalPager;
import com.cappielloantonio.play.util.MusicUtil;
import com.cappielloantonio.play.util.PreferenceUtil;
import com.cappielloantonio.play.viewmodel.PlayerBottomSheetViewModel;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
@ -41,6 +46,8 @@ public class PlayerControllerFragment extends Fragment {
private ToggleButton buttonFavorite;
private TextView playerMediaTitleLabel;
private TextView playerArtistNameLabel;
private Button playbackSpeedButton;
private ToggleButton skipSilenceToggleButton;
private MainActivity activity;
private PlayerBottomSheetViewModel playerBottomSheetViewModel;
@ -60,6 +67,7 @@ public class PlayerControllerFragment extends Fragment {
initMediaListenable();
initArtistLabelButton();
return view;
}
@ -90,6 +98,8 @@ public class PlayerControllerFragment extends Fragment {
buttonFavorite = bind.getRoot().findViewById(R.id.button_favorite);
playerMediaTitleLabel = bind.getRoot().findViewById(R.id.player_media_title_label);
playerArtistNameLabel = bind.getRoot().findViewById(R.id.player_artist_name_label);
playbackSpeedButton = bind.getRoot().findViewById(R.id.player_playback_speed_button);
skipSilenceToggleButton = bind.getRoot().findViewById(R.id.player_skip_silence_toggle_button);
playerMoveDownBottomSheet.setOnClickListener(view -> activity.collapseBottomSheet());
}
@ -120,11 +130,13 @@ public class PlayerControllerFragment extends Fragment {
@SuppressLint("UnsafeOptInUsageError")
private void setMediaControllerListener(MediaBrowser mediaBrowser) {
setMediaControllerUI(mediaBrowser);
setMetadata(mediaBrowser.getMediaMetadata());
mediaBrowser.addListener(new Player.Listener() {
@Override
public void onMediaMetadataChanged(@NonNull MediaMetadata mediaMetadata) {
setMediaControllerUI(mediaBrowser);
setMetadata(mediaMetadata);
}
});
@ -139,6 +151,39 @@ public class PlayerControllerFragment extends Fragment {
playerArtistNameLabel.setSelected(true);
}
@SuppressLint("UnsafeOptInUsageError")
private void setMediaControllerUI(MediaBrowser mediaBrowser) {
initPlaybackSpeedButton(mediaBrowser);
if (mediaBrowser.getMediaMetadata().extras != null) {
switch (mediaBrowser.getMediaMetadata().extras.getString("mediaType", Media.MEDIA_TYPE_MUSIC)) {
case Media.MEDIA_TYPE_PODCAST:
bind.getRoot().setShowShuffleButton(false);
bind.getRoot().setShowRewindButton(true);
bind.getRoot().setShowPreviousButton(false);
bind.getRoot().setShowNextButton(false);
bind.getRoot().setShowFastForwardButton(true);
bind.getRoot().setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE);
bind.getRoot().findViewById(R.id.player_playback_speed_button).setVisibility(View.VISIBLE);
bind.getRoot().findViewById(R.id.player_skip_silence_toggle_button).setVisibility(View.VISIBLE);
setPlaybackParameters(mediaBrowser);
break;
case Media.MEDIA_TYPE_MUSIC:
default:
bind.getRoot().setShowShuffleButton(true);
bind.getRoot().setShowRewindButton(false);
bind.getRoot().setShowPreviousButton(true);
bind.getRoot().setShowNextButton(true);
bind.getRoot().setShowFastForwardButton(false);
bind.getRoot().setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL | RepeatModeUtil.REPEAT_TOGGLE_MODE_ONE);
bind.getRoot().findViewById(R.id.player_playback_speed_button).setVisibility(View.GONE);
bind.getRoot().findViewById(R.id.player_skip_silence_toggle_button).setVisibility(View.GONE);
resetPlaybackParameters(mediaBrowser);
break;
}
}
}
private void initCoverLyricsSlideView() {
playerMediaCoverViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
playerMediaCoverViewPager.setAdapter(new PlayerControllerHorizontalPager(this));
@ -195,6 +240,43 @@ public class PlayerControllerFragment extends Fragment {
});
}
@SuppressLint("UnsafeOptInUsageError")
private void initPlaybackSpeedButton(MediaBrowser mediaBrowser) {
playbackSpeedButton.setOnClickListener(view -> {
float currentSpeed = PreferenceUtil.getInstance(requireContext()).getPlaybackSpeed();
if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_080) {
mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_100));
playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_100));
PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_100);
} else if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_100) {
mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_125));
playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_125));
PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_125);
} else if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_125) {
mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_150));
playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_150));
PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_150);
} else if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_150) {
mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_175));
playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_175));
PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_175);
} else if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_175) {
mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_200));
playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_200));
PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_200);
} else if (currentSpeed == Media.MEDIA_PLAYBACK_SPEED_200) {
mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_080));
playbackSpeedButton.setText(getString(R.string.player_playback_speed, Media.MEDIA_PLAYBACK_SPEED_080));
PreferenceUtil.getInstance(requireContext()).setPlaybackSpeed(Media.MEDIA_PLAYBACK_SPEED_080);
}
});
skipSilenceToggleButton.setOnClickListener(view -> {
PreferenceUtil.getInstance(requireContext()).setSkipSilenceMode(!skipSilenceToggleButton.isChecked());
});
}
public void goToControllerPage() {
playerMediaCoverViewPager.setCurrentItem(0, false);
}
@ -202,4 +284,23 @@ public class PlayerControllerFragment extends Fragment {
public void goToLyricsPage() {
playerMediaCoverViewPager.setCurrentItem(1, true);
}
@SuppressLint("UnsafeOptInUsageError")
private void setPlaybackParameters(MediaBrowser mediaBrowser) {
Button playbackSpeedButton = bind.getRoot().findViewById(R.id.player_playback_speed_button);
float currentSpeed = PreferenceUtil.getInstance(requireContext()).getPlaybackSpeed();
boolean skipSilence = PreferenceUtil.getInstance(requireContext()).isSkipSilenceMode();
mediaBrowser.setPlaybackParameters(new PlaybackParameters(currentSpeed));
playbackSpeedButton.setText(getString(R.string.player_playback_speed, currentSpeed));
// TODO Skippare il silenzio
skipSilenceToggleButton.setChecked(skipSilence);
}
@SuppressLint("UnsafeOptInUsageError")
private void resetPlaybackParameters(MediaBrowser mediaBrowser) {
mediaBrowser.setPlaybackParameters(new PlaybackParameters(Media.MEDIA_PLAYBACK_SPEED_100));
// TODO Resettare lo skip del silenzio
}
}

View file

@ -7,4 +7,6 @@
app:controller_layout_id="@layout/inner_fragment_player_controller_layout"
app:repeat_toggle_modes="all|one"
app:show_shuffle_button="true"
app:show_rewind_button="false"
app:show_fastforward_button="false"
app:show_timeout="0" />

View file

@ -145,6 +145,25 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/exo_progress" />
<View
android:id="@+id/placeholder_view_left"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="24dp"
app:layout_constraintBottom_toBottomOf="@+id/placeholder_view_middle_left"
app:layout_constraintEnd_toStartOf="@+id/placeholder_view_middle_left"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/placeholder_view_middle_left" />
<View
android:id="@+id/placeholder_view_middle_left"
android:layout_width="42dp"
android:layout_height="42dp"
app:layout_constraintBottom_toBottomOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintEnd_toStartOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintStart_toEndOf="@id/placeholder_view_left"
app:layout_constraintTop_toTopOf="@+id/player_play_pause_placeholder_view" />
<View
android:id="@+id/player_play_pause_placeholder_view"
android:layout_width="70dp"
@ -156,6 +175,42 @@
app:layout_constraintTop_toBottomOf="@+id/exo_progress"
app:layout_constraintVertical_bias=".60" />
<View
android:id="@+id/placeholder_view_middle_right"
android:layout_width="42dp"
android:layout_height="42dp"
app:layout_constraintBottom_toBottomOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintEnd_toStartOf="@id/placeholder_view_right"
app:layout_constraintStart_toEndOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintTop_toTopOf="@+id/player_play_pause_placeholder_view" />
<View
android:id="@+id/placeholder_view_right"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginEnd="24dp"
app:layout_constraintBottom_toBottomOf="@+id/placeholder_view_middle_right"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/placeholder_view_middle_right"
app:layout_constraintTop_toTopOf="@+id/placeholder_view_middle_right" />
<Button
android:id="@+id/player_playback_speed_button"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginStart="24dp"
android:insetLeft="0dp"
android:insetTop="0dp"
android:insetRight="0dp"
android:insetBottom="0dp"
app:cornerRadius="30dp"
app:layout_constraintBottom_toBottomOf="@+id/placeholder_view_middle_left"
app:layout_constraintEnd_toStartOf="@+id/placeholder_view_middle_left"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/placeholder_view_middle_left"
app:tint="?attr/colorOnPrimaryContainer" />
<ImageButton
android:id="@+id/exo_shuffle"
android:layout_width="32dp"
@ -163,13 +218,26 @@
android:layout_marginStart="24dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:scaleType="fitCenter"
app:layout_constraintBottom_toBottomOf="@+id/exo_prev"
app:layout_constraintEnd_toStartOf="@+id/exo_prev"
app:layout_constraintBottom_toBottomOf="@+id/placeholder_view_middle_left"
app:layout_constraintEnd_toStartOf="@+id/placeholder_view_middle_left"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/exo_prev"
app:layout_constraintTop_toTopOf="@+id/placeholder_view_middle_left"
app:srcCompat="@drawable/ic_shuffle"
app:tint="?attr/colorOnPrimaryContainer" />
<ImageButton
android:id="@+id/exo_rew"
android:layout_width="42dp"
android:layout_height="42dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:scaleType="fitCenter"
android:src="@drawable/ic_replay"
app:layout_constraintBottom_toBottomOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintEnd_toStartOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintStart_toEndOf="@id/placeholder_view_left"
app:layout_constraintTop_toTopOf="@+id/player_play_pause_placeholder_view"
app:tint="?attr/colorOnPrimaryContainer" />
<ImageButton
android:id="@+id/exo_prev"
android:layout_width="42dp"
@ -178,7 +246,7 @@
android:scaleType="fitCenter"
app:layout_constraintBottom_toBottomOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintEnd_toStartOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintStart_toEndOf="@id/exo_shuffle"
app:layout_constraintStart_toEndOf="@id/placeholder_view_left"
app:layout_constraintTop_toTopOf="@+id/player_play_pause_placeholder_view"
app:srcCompat="@drawable/ic_skip_previous"
app:tint="?attr/colorOnPrimaryContainer" />
@ -222,12 +290,25 @@
android:background="?attr/selectableItemBackgroundBorderless"
android:scaleType="fitCenter"
app:layout_constraintBottom_toBottomOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintEnd_toStartOf="@id/exo_repeat_toggle"
app:layout_constraintEnd_toStartOf="@id/placeholder_view_right"
app:layout_constraintStart_toEndOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintTop_toTopOf="@+id/player_play_pause_placeholder_view"
app:srcCompat="@drawable/ic_skip_next"
app:tint="?attr/colorOnPrimaryContainer" />
<ImageButton
android:id="@+id/exo_ffwd"
android:layout_width="42dp"
android:layout_height="42dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:scaleType="fitCenter"
app:layout_constraintBottom_toBottomOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintEnd_toStartOf="@id/placeholder_view_right"
app:layout_constraintStart_toEndOf="@+id/player_play_pause_placeholder_view"
app:layout_constraintTop_toTopOf="@+id/player_play_pause_placeholder_view"
app:srcCompat="@drawable/ic_forward"
app:tint="?attr/colorOnPrimaryContainer" />
<ImageButton
android:id="@+id/exo_repeat_toggle"
android:layout_width="32dp"
@ -235,11 +316,25 @@
android:layout_marginEnd="24dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:scaleType="fitCenter"
app:layout_constraintBottom_toBottomOf="@+id/exo_next"
app:layout_constraintBottom_toBottomOf="@+id/placeholder_view_middle_right"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/exo_next"
app:layout_constraintTop_toTopOf="@+id/exo_next"
app:layout_constraintStart_toEndOf="@+id/placeholder_view_middle_right"
app:layout_constraintTop_toTopOf="@+id/placeholder_view_middle_right"
app:srcCompat="@drawable/ic_repeat"
app:tint="?attr/colorOnPrimaryContainer" />
<ToggleButton
android:id="@+id/player_skip_silence_toggle_button"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="24dp"
android:background="@drawable/button_skip_silence_selector"
android:text=""
android:textOff=""
android:textOn=""
app:layout_constraintBottom_toBottomOf="@+id/placeholder_view_middle_right"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/placeholder_view_middle_right"
app:layout_constraintTop_toTopOf="@+id/placeholder_view_middle_right"
app:tint="?attr/colorOnPrimaryContainer" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -26,7 +26,7 @@
android:maxLines="1"
android:paddingStart="8dp"
android:paddingEnd="8dp"
app:layout_constraintEnd_toStartOf="@+id/player_header_button"
app:layout_constraintEnd_toStartOf="@+id/placeholder_left_view"
app:layout_constraintStart_toEndOf="@+id/player_header_media_cover_image"
app:layout_constraintTop_toTopOf="parent" />
@ -39,10 +39,43 @@
android:maxLines="1"
android:paddingStart="8dp"
android:paddingEnd="8dp"
app:layout_constraintEnd_toStartOf="@+id/player_header_button"
app:layout_constraintEnd_toStartOf="@+id/placeholder_left_view"
app:layout_constraintStart_toEndOf="@+id/player_header_media_cover_image"
app:layout_constraintTop_toBottomOf="@+id/player_header_media_title_label" />
<View
android:id="@+id/placeholder_left_view"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
app:layout_constraintBottom_toTopOf="@+id/player_header_seek_bar"
app:layout_constraintEnd_toStartOf="@+id/player_header_button"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/placeholder_right_view"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
app:layout_constraintBottom_toTopOf="@+id/player_header_seek_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/player_header_rewind_media_button"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:background="@drawable/ic_replay"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/player_header_seek_bar"
app:layout_constraintEnd_toStartOf="@+id/player_header_button"
app:layout_constraintTop_toTopOf="parent" />
<ToggleButton
android:id="@+id/player_header_button"
android:layout_width="28dp"
@ -56,7 +89,7 @@
android:textOff=""
android:textOn=""
app:layout_constraintBottom_toTopOf="@+id/player_header_seek_bar"
app:layout_constraintEnd_toStartOf="@+id/player_header_next_media_button"
app:layout_constraintEnd_toStartOf="@+id/placeholder_right_view"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
@ -71,6 +104,19 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/player_header_fast_forward_media_button"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:background="@drawable/ic_forward"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/player_header_seek_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<SeekBar
android:id="@+id/player_header_seek_bar"
android:layout_width="match_parent"

View file

@ -110,6 +110,7 @@
<string name="menu_unpin_button">Unpin</string>
<string name="player_bottom_sheet_title">Now playing</string>
<string name="player_song_lyrics_none_available_label">No lyrics available</string>
<string name="player_playback_speed">%1$.2fx</string>
<string name="playlist_catalogue_title">Playlist Catalogue</string>
<string name="playlist_catalogue_title_expanded">Browse Playlists</string>
<string name="playlist_chooser_dialog_empty">No playlists created</string>