From c9cf86acb576b4f084ae0b75516f4a425d8edefe Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 2 Mar 2026 00:48:15 -0300 Subject: [PATCH] feat: toggle player bitrate visibility on touch (#466) * feat: touch player chip to toggle bitrate visibility * feat: player bitrate visibility is remembered * fix: player landscape layout not grouping chip with textview * feat: touch bitrate to toggle its visibility This catches the edge case where the the chip is not reachable due to insuficient horizontal space --------- Co-authored-by: eddyizm --- .../ui/fragment/PlayerControllerFragment.java | 27 +++++++++- .../tempo/util/Preferences.kt | 11 ++++ ...nner_fragment_player_controller_layout.xml | 50 ++++++++++++------- ...nner_fragment_player_controller_layout.xml | 50 ++++++++++++------- 4 files changed, 98 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerControllerFragment.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerControllerFragment.java index 3bba6183..3c14788b 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerControllerFragment.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/PlayerControllerFragment.java @@ -8,9 +8,11 @@ import android.os.Bundle; import android.os.IBinder; import android.text.TextUtils; import android.util.Log; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.Button; import android.widget.ImageButton; import android.widget.LinearLayout; @@ -33,6 +35,10 @@ import androidx.media3.session.SessionToken; import androidx.navigation.NavController; import androidx.navigation.NavOptions; import androidx.navigation.fragment.NavHostFragment; +import androidx.transition.ChangeBounds; +import androidx.transition.Slide; +import androidx.transition.TransitionManager; +import androidx.transition.TransitionSet; import androidx.viewpager2.widget.ViewPager2; import com.cappielloantonio.tempo.R; @@ -56,7 +62,6 @@ import com.google.android.material.elevation.SurfaceColors; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; -import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -314,7 +319,7 @@ public class PlayerControllerFragment extends Fragment { if (!samplingRate.trim().isEmpty()) items.add(samplingRate); String mediaQuality = TextUtils.join(" • ", items); - playerMediaBitrate.setVisibility(View.VISIBLE); + playerMediaBitrate.setVisibility(Preferences.getBitrateVisible() ? View.VISIBLE : View.GONE); playerMediaBitrate.setText(isLocal ? mediaQuality : mediaQuality); } } @@ -335,7 +340,25 @@ public class PlayerControllerFragment extends Fragment { TrackInfoDialog dialog = new TrackInfoDialog(mediaMetadata); dialog.show(activity.getSupportFragmentManager(), null); }); + + playerMediaExtension.setOnClickListener( v -> toggleBitrateVisibility() ); + playerMediaBitrate.setOnClickListener(v -> toggleBitrateVisibility() ); } + + private void toggleBitrateVisibility() { + ViewGroup parent = (ViewGroup) playerMediaBitrate.getParent(); + + TransitionSet transition = new TransitionSet() + .addTransition(new Slide(Gravity.START)) + .addTransition(new ChangeBounds()) + .setDuration(500) + .setInterpolator(new AccelerateDecelerateInterpolator()); + TransitionManager.beginDelayedTransition(parent, transition); + + playerMediaBitrate.setVisibility(Preferences.getBitrateVisible() ? View.GONE : View.VISIBLE); + Preferences.setBitrateVisible(!Preferences.getBitrateVisible()); + } + private void updateAssetLinkChips(MediaMetadata mediaMetadata) { if (assetLinkChipGroup == null) return; String mediaType = mediaMetadata.extras != null ? mediaMetadata.extras.getString("type", Constants.MEDIA_TYPE_MUSIC) : Constants.MEDIA_TYPE_MUSIC; diff --git a/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt b/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt index 1edc914e..099a471d 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt +++ b/app/src/main/java/com/cappielloantonio/tempo/util/Preferences.kt @@ -25,6 +25,7 @@ object Preferences { private const val IN_USE_SERVER_ADDRESS = "in_use_server_address" private const val NEXT_SERVER_SWITCH = "next_server_switch" private const val PLAYBACK_SPEED = "playback_speed" + private const val BITRATE_VISIBLE = "bitrate_visible" private const val SKIP_SILENCE = "skip_silence" private const val SHUFFLE_MODE = "shuffle_mode" private const val REPEAT_MODE = "repeat_mode" @@ -292,6 +293,16 @@ object Preferences { App.getInstance().preferences.edit().putFloat(PLAYBACK_SPEED, playbackSpeed).apply() } + @JvmStatic + fun getBitrateVisible(): Boolean { + return App.getInstance().preferences.getBoolean(BITRATE_VISIBLE, true) + } + + @JvmStatic + fun setBitrateVisible(bitrateVisible: Boolean) { + App.getInstance().preferences.edit().putBoolean(BITRATE_VISIBLE, bitrateVisible).apply() + } + @JvmStatic fun isSkipSilenceMode(): Boolean { return App.getInstance().preferences.getBoolean(SKIP_SILENCE, false) diff --git a/app/src/main/res/layout-land/inner_fragment_player_controller_layout.xml b/app/src/main/res/layout-land/inner_fragment_player_controller_layout.xml index 435e3648..b2757648 100644 --- a/app/src/main/res/layout-land/inner_fragment_player_controller_layout.xml +++ b/app/src/main/res/layout-land/inner_fragment_player_controller_layout.xml @@ -24,30 +24,42 @@ app:layout_constraintStart_toEndOf="@+id/vertical_guideline" app:layout_constraintTop_toTopOf="parent"> - + app:layout_constraintEnd_toEndOf="parent"> - + + + + + - + app:layout_constraintEnd_toEndOf="parent"> - + + + + +