Update long press layout for large display sizes

- Allow text to marquee when too large
- Adjust margins for text and buttons
- Hide settings button if there is not enough room to display

Fixes: 187900686
Fixes: 186756165
Test: visual
Change-Id: I3b10fded9f6633d6486c58b3fcebd8006168144d
This commit is contained in:
Beth Thibodeau
2021-05-14 19:16:55 -04:00
parent 740e4584fd
commit 5b7117f07d
8 changed files with 136 additions and 53 deletions

View File

@@ -159,36 +159,43 @@
<!-- Long press menu -->
<TextView
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/qs_media_padding"
android:layout_marginTop="20dp"
android:layout_marginStart="@dimen/qs_media_padding"
android:layout_marginEnd="@dimen/qs_media_padding"
android:id="@+id/remove_text"
android:fontFamily="@*android:string/config_headlineFontFamily"
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:text="@string/controls_media_close_session"
android:gravity="center_horizontal|top"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/settings"/>
app:layout_constraintBottom_toTopOf="@id/cancel"/>
<FrameLayout
android:id="@+id/settings"
android:background="@drawable/qs_media_light_source"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/qs_media_padding"
android:paddingBottom="@dimen/qs_media_padding"
android:minWidth="48dp"
android:minHeight="48dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginEnd="@dimen/qs_media_info_spacing"
android:layout_marginBottom="@dimen/qs_media_padding"
android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/remove_text">
<TextView
android:layout_gravity="bottom"
android:id="@+id/settings_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MediaPlayer.OutlineButton"
@@ -198,18 +205,21 @@
<FrameLayout
android:id="@+id/cancel"
android:background="@drawable/qs_media_light_source"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:paddingBottom="@dimen/qs_media_padding"
android:minWidth="48dp"
android:minHeight="48dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="@dimen/qs_media_info_spacing"
android:layout_marginEnd="@dimen/qs_media_info_spacing"
android:layout_marginBottom="@dimen/qs_media_padding"
android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
app:layout_constraintStart_toEndOf="@id/settings"
app:layout_constraintEnd_toStartOf="@id/dismiss"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/remove_text">
<TextView
android:layout_gravity="bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MediaPlayer.OutlineButton"
@@ -219,23 +229,25 @@
<FrameLayout
android:id="@+id/dismiss"
android:background="@drawable/qs_media_light_source"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/qs_media_info_spacing"
android:layout_marginEnd="@dimen/qs_media_padding"
android:paddingBottom="@dimen/qs_media_padding"
android:minWidth="48dp"
android:minHeight="48dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="@dimen/qs_media_padding"
android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
app:layout_constraintStart_toEndOf="@id/cancel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/remove_text">
<TextView
android:layout_gravity="bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MediaPlayer.OutlineButton"
android:text="@string/controls_media_dismiss_button"
/>
/>
</FrameLayout>
</com.android.systemui.util.animation.TransitionLayout>

View File

@@ -213,36 +213,43 @@
<!-- Long press menu -->
<TextView
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/qs_media_padding"
android:layout_marginTop="20dp"
android:layout_marginStart="@dimen/qs_media_padding"
android:layout_marginEnd="@dimen/qs_media_padding"
android:id="@+id/remove_text"
android:fontFamily="@*android:string/config_headlineFontFamily"
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:text="@string/controls_media_close_session"
android:gravity="center_horizontal|top"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/settings"/>
app:layout_constraintBottom_toTopOf="@id/cancel"/>
<FrameLayout
android:id="@+id/settings"
android:background="@drawable/qs_media_light_source"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/qs_media_padding"
android:paddingBottom="@dimen/qs_media_padding"
android:minWidth="48dp"
android:minHeight="48dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginEnd="@dimen/qs_media_info_spacing"
android:layout_marginBottom="@dimen/qs_media_padding"
android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/remove_text">
<TextView
android:layout_gravity="bottom"
android:id="@+id/settings_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MediaPlayer.OutlineButton"
@@ -252,18 +259,21 @@
<FrameLayout
android:id="@+id/cancel"
android:background="@drawable/qs_media_light_source"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:paddingBottom="@dimen/qs_media_padding"
android:minWidth="48dp"
android:minHeight="48dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="@dimen/qs_media_info_spacing"
android:layout_marginEnd="@dimen/qs_media_info_spacing"
android:layout_marginBottom="@dimen/qs_media_padding"
android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
app:layout_constraintStart_toEndOf="@id/settings"
app:layout_constraintEnd_toStartOf="@id/dismiss"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/remove_text">
<TextView
android:layout_gravity="bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MediaPlayer.OutlineButton"
@@ -273,18 +283,21 @@
<FrameLayout
android:id="@+id/dismiss"
android:background="@drawable/qs_media_light_source"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/qs_media_info_spacing"
android:layout_marginEnd="@dimen/qs_media_padding"
android:paddingBottom="@dimen/qs_media_padding"
android:minWidth="48dp"
android:minHeight="48dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="@dimen/qs_media_padding"
android:layout_marginTop="6dp"
app:layout_constrainedWidth="true"
app:layout_constraintWidth_min="48dp"
app:layout_constraintHeight_min="48dp"
app:layout_constraintStart_toEndOf="@id/cancel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/remove_text">
<TextView
android:layout_gravity="bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MediaPlayer.OutlineButton"

View File

@@ -646,6 +646,8 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:backgroundTint">@color/media_player_outline_button_bg</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
<item name="android:layout_gravity">center</item>
<item name="android:singleLine">true</item>
</style>
<style name="MediaPlayer.SolidButton">

View File

@@ -34,6 +34,7 @@ import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.os.Bundle;
import android.text.Layout;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
@@ -211,7 +212,7 @@ public class MediaControlPanel {
mPlayerViewHolder.getPlayer().setOnLongClickListener(v -> {
if (!mMediaViewController.isGutsVisible()) {
mMediaViewController.openGuts();
openGuts();
return true;
} else {
closeGuts();
@@ -235,7 +236,7 @@ public class MediaControlPanel {
mRecommendationViewHolder.getRecommendations().setOnLongClickListener(v -> {
if (!mMediaViewController.isGutsVisible()) {
mMediaViewController.openGuts();
openGuts();
return true;
} else {
return false;
@@ -424,7 +425,7 @@ public class MediaControlPanel {
// Guts label
boolean isDismissible = data.isClearable();
mPlayerViewHolder.getSettingsText().setText(isDismissible
mPlayerViewHolder.getLongPressText().setText(isDismissible
? R.string.controls_media_close_session
: R.string.controls_media_active_session);
@@ -590,6 +591,11 @@ public class MediaControlPanel {
* @param immediate {@code true} if it should be closed without animation
*/
public void closeGuts(boolean immediate) {
if (mPlayerViewHolder != null) {
mPlayerViewHolder.marquee(false, mMediaViewController.GUTS_ANIMATION_DURATION);
} else if (mRecommendationViewHolder != null) {
mRecommendationViewHolder.marquee(false, mMediaViewController.GUTS_ANIMATION_DURATION);
}
mMediaViewController.closeGuts(immediate);
}
@@ -597,6 +603,32 @@ public class MediaControlPanel {
closeGuts(false);
}
private void openGuts() {
ConstraintSet expandedSet = mMediaViewController.getExpandedLayout();
ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout();
boolean wasTruncated = false;
Layout l = null;
if (mPlayerViewHolder != null) {
mPlayerViewHolder.marquee(true, mMediaViewController.GUTS_ANIMATION_DURATION);
l = mPlayerViewHolder.getSettingsText().getLayout();
} else if (mRecommendationViewHolder != null) {
mRecommendationViewHolder.marquee(true, mMediaViewController.GUTS_ANIMATION_DURATION);
l = mRecommendationViewHolder.getSettingsText().getLayout();
}
if (l != null) {
wasTruncated = l.getEllipsisCount(0) > 0;
}
mMediaViewController.setShouldHideGutsSettings(wasTruncated);
if (wasTruncated) {
// not enough room for the settings button to show fully, let's hide it
expandedSet.constrainMaxWidth(R.id.settings, 0);
collapsedSet.constrainMaxWidth(R.id.settings, 0);
}
mMediaViewController.openGuts();
}
@UiThread
private Drawable scaleDrawable(Icon icon) {
if (icon == null) {

View File

@@ -185,6 +185,11 @@ class MediaViewController @Inject constructor(
var isGutsVisible = false
private set
/**
* Whether the settings button in the guts should be visible
*/
var shouldHideGutsSettings = false
init {
mediaHostStatesManager.addController(this)
layoutController.sizeChangedListener = { width: Int, height: Int ->
@@ -277,6 +282,9 @@ class MediaViewController @Inject constructor(
viewState.widgetStates.get(id)?.gone = !isGutsVisible
}
}
if (shouldHideGutsSettings) {
viewState.widgetStates.get(R.id.settings)?.gone = true
}
}
/**

View File

@@ -59,11 +59,12 @@ class PlayerViewHolder private constructor(itemView: View) {
val action4 = itemView.requireViewById<ImageButton>(R.id.action4)
// Settings screen
val settingsText = itemView.requireViewById<TextView>(R.id.remove_text)
val longPressText = itemView.requireViewById<TextView>(R.id.remove_text)
val cancel = itemView.requireViewById<View>(R.id.cancel)
val dismiss = itemView.requireViewById<ViewGroup>(R.id.dismiss)
val dismissLabel = dismiss.getChildAt(0)
val settings = itemView.requireViewById<View>(R.id.settings)
val settingsText = itemView.requireViewById<TextView>(R.id.settings_text)
init {
(player.background as IlluminationDrawable).let {
@@ -92,6 +93,10 @@ class PlayerViewHolder private constructor(itemView: View) {
}
}
fun marquee(start: Boolean, delay: Long) {
longPressText.getHandler().postDelayed({ longPressText.setSelected(start) }, delay)
}
companion object {
/**
* Creates a PlayerViewHolder.

View File

@@ -63,10 +63,12 @@ class RecommendationViewHolder private constructor(itemView: View) {
R.id.media_logo6)
// Settings/Guts screen
val longPressText = itemView.requireViewById<TextView>(R.id.remove_text)
val cancel = itemView.requireViewById<View>(R.id.cancel)
val dismiss = itemView.requireViewById<ViewGroup>(R.id.dismiss)
val dismissLabel = dismiss.getChildAt(0)
val settings = itemView.requireViewById<View>(R.id.settings)
val settingsText = itemView.requireViewById<TextView>(R.id.settings_text)
init {
(recommendations.background as IlluminationDrawable).let { background ->
@@ -79,6 +81,10 @@ class RecommendationViewHolder private constructor(itemView: View) {
}
}
fun marquee(start: Boolean, delay: Long) {
longPressText.getHandler().postDelayed({ longPressText.setSelected(start) }, delay)
}
companion object {
/**
* Creates a RecommendationViewHolder.

View File

@@ -23,6 +23,7 @@ import android.graphics.drawable.RippleDrawable
import android.media.MediaMetadata
import android.media.session.MediaSession
import android.media.session.PlaybackState
import android.os.Handler
import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
@@ -110,8 +111,10 @@ public class MediaControlPanelTest : SysuiTestCase() {
private lateinit var action2: ImageButton
private lateinit var action3: ImageButton
private lateinit var action4: ImageButton
private lateinit var settingsText: TextView
@Mock private lateinit var longPressText: TextView
@Mock private lateinit var handler: Handler
private lateinit var settings: View
private lateinit var settingsText: TextView
private lateinit var cancel: View
private lateinit var dismiss: FrameLayout
private lateinit var dismissLabel: View
@@ -170,10 +173,12 @@ public class MediaControlPanelTest : SysuiTestCase() {
whenever(holder.action3).thenReturn(action3)
action4 = ImageButton(context)
whenever(holder.action4).thenReturn(action4)
settingsText = TextView(context)
whenever(holder.settingsText).thenReturn(settingsText)
whenever(holder.longPressText).thenReturn(longPressText)
whenever(longPressText.handler).thenReturn(handler)
settings = View(context)
whenever(holder.settings).thenReturn(settings)
settingsText = TextView(context)
whenever(holder.settingsText).thenReturn(settingsText)
cancel = View(context)
whenever(holder.cancel).thenReturn(cancel)
dismiss = FrameLayout(context)