Merge "Add progress bar in media recommendation layout." into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
2742fd7482
@@ -62,4 +62,24 @@
|
|||||||
android:textSize="11sp"
|
android:textSize="11sp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:layout_gravity="bottom"/>
|
android:layout_gravity="bottom"/>
|
||||||
|
|
||||||
|
<!-- Seek Bar -->
|
||||||
|
<SeekBar
|
||||||
|
android:id="@+id/media_progress_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="12dp"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:maxHeight="@dimen/qs_media_enabled_seekbar_height"
|
||||||
|
android:thumb="@android:color/transparent"
|
||||||
|
android:splitTrack="false"
|
||||||
|
android:clickable="false"
|
||||||
|
android:progressTint="?android:attr/textColorPrimary"
|
||||||
|
android:progressBackgroundTint="?android:attr/textColorTertiary"
|
||||||
|
android:paddingTop="5dp"
|
||||||
|
android:paddingBottom="5dp"
|
||||||
|
android:paddingStart="0dp"
|
||||||
|
android:paddingEnd="0dp"
|
||||||
|
android:layout_marginEnd="@dimen/qs_media_info_spacing"
|
||||||
|
android:layout_marginStart="@dimen/qs_media_info_spacing"
|
||||||
|
android:layout_marginBottom="@dimen/qs_media_info_spacing"/>
|
||||||
</merge>
|
</merge>
|
||||||
@@ -20,6 +20,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
|
import android.widget.SeekBar
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.android.internal.widget.CachingIconView
|
import com.android.internal.widget.CachingIconView
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
@@ -37,6 +38,7 @@ class RecommendationViewHolder private constructor(itemView: View, updatedView:
|
|||||||
// Recommendation screen
|
// Recommendation screen
|
||||||
lateinit var cardIcon: ImageView
|
lateinit var cardIcon: ImageView
|
||||||
lateinit var mediaAppIcons: List<CachingIconView>
|
lateinit var mediaAppIcons: List<CachingIconView>
|
||||||
|
lateinit var mediaProgressBars: List<SeekBar>
|
||||||
lateinit var cardTitle: TextView
|
lateinit var cardTitle: TextView
|
||||||
|
|
||||||
val mediaCoverContainers =
|
val mediaCoverContainers =
|
||||||
@@ -82,6 +84,13 @@ class RecommendationViewHolder private constructor(itemView: View, updatedView:
|
|||||||
if (updatedView) {
|
if (updatedView) {
|
||||||
mediaAppIcons = mediaCoverContainers.map { it.requireViewById(R.id.media_rec_app_icon) }
|
mediaAppIcons = mediaCoverContainers.map { it.requireViewById(R.id.media_rec_app_icon) }
|
||||||
cardTitle = itemView.requireViewById(R.id.media_rec_title)
|
cardTitle = itemView.requireViewById(R.id.media_rec_title)
|
||||||
|
mediaProgressBars =
|
||||||
|
mediaCoverContainers.map {
|
||||||
|
it.requireViewById<SeekBar?>(R.id.media_progress_bar).apply {
|
||||||
|
// Media playback is in the direction of tape, not time, so it stays LTR
|
||||||
|
layoutDirection = View.LAYOUT_DIRECTION_LTR
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cardIcon = itemView.requireViewById<ImageView>(R.id.recommendation_card_icon)
|
cardIcon = itemView.requireViewById<ImageView>(R.id.recommendation_card_icon)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ import android.view.ViewGroup;
|
|||||||
import android.view.animation.Interpolator;
|
import android.view.animation.Interpolator;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -1366,6 +1367,24 @@ public class MediaControlPanel {
|
|||||||
hasSubtitle |= !TextUtils.isEmpty(subtitle);
|
hasSubtitle |= !TextUtils.isEmpty(subtitle);
|
||||||
TextView subtitleView = mRecommendationViewHolder.getMediaSubtitles().get(itemIndex);
|
TextView subtitleView = mRecommendationViewHolder.getMediaSubtitles().get(itemIndex);
|
||||||
subtitleView.setText(subtitle);
|
subtitleView.setText(subtitle);
|
||||||
|
|
||||||
|
// Set up progress bar
|
||||||
|
if (mFeatureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)) {
|
||||||
|
SeekBar mediaProgressBar =
|
||||||
|
mRecommendationViewHolder.getMediaProgressBars().get(itemIndex);
|
||||||
|
TextView mediaSubtitle =
|
||||||
|
mRecommendationViewHolder.getMediaSubtitles().get(itemIndex);
|
||||||
|
// show progress bar if the recommended album is played.
|
||||||
|
Double progress = MediaDataUtils.getDescriptionProgress(recommendation.getExtras());
|
||||||
|
if (progress == null || progress <= 0.0) {
|
||||||
|
mediaProgressBar.setVisibility(View.GONE);
|
||||||
|
mediaSubtitle.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
mediaProgressBar.setProgress((int) (progress * 100));
|
||||||
|
mediaProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
mediaSubtitle.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mSmartspaceMediaItemsCount = NUM_REQUIRED_RECOMMENDATIONS;
|
mSmartspaceMediaItemsCount = NUM_REQUIRED_RECOMMENDATIONS;
|
||||||
|
|
||||||
@@ -1440,6 +1459,12 @@ public class MediaControlPanel {
|
|||||||
(title) -> title.setTextColor(textPrimaryColor));
|
(title) -> title.setTextColor(textPrimaryColor));
|
||||||
mRecommendationViewHolder.getMediaSubtitles().forEach(
|
mRecommendationViewHolder.getMediaSubtitles().forEach(
|
||||||
(subtitle) -> subtitle.setTextColor(textSecondaryColor));
|
(subtitle) -> subtitle.setTextColor(textSecondaryColor));
|
||||||
|
if (mFeatureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)) {
|
||||||
|
mRecommendationViewHolder.getMediaProgressBars().forEach(
|
||||||
|
(progressBar) -> progressBar.setProgressTintList(
|
||||||
|
ColorStateList.valueOf(textPrimaryColor))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
mRecommendationViewHolder.getGutsViewHolder().setColors(colorScheme);
|
mRecommendationViewHolder.getGutsViewHolder().setColors(colorScheme);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import android.widget.TextView
|
|||||||
import androidx.constraintlayout.widget.Barrier
|
import androidx.constraintlayout.widget.Barrier
|
||||||
import androidx.constraintlayout.widget.ConstraintSet
|
import androidx.constraintlayout.widget.ConstraintSet
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.media.utils.MediaConstants
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.internal.logging.InstanceId
|
import com.android.internal.logging.InstanceId
|
||||||
import com.android.internal.widget.CachingIconView
|
import com.android.internal.widget.CachingIconView
|
||||||
@@ -206,6 +207,12 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
@Mock private lateinit var coverContainer3: ViewGroup
|
@Mock private lateinit var coverContainer3: ViewGroup
|
||||||
@Mock private lateinit var recAppIconItem: CachingIconView
|
@Mock private lateinit var recAppIconItem: CachingIconView
|
||||||
@Mock private lateinit var recCardTitle: TextView
|
@Mock private lateinit var recCardTitle: TextView
|
||||||
|
@Mock private lateinit var recProgressBar1: SeekBar
|
||||||
|
@Mock private lateinit var recProgressBar2: SeekBar
|
||||||
|
@Mock private lateinit var recProgressBar3: SeekBar
|
||||||
|
@Mock private lateinit var recSubtitleMock1: TextView
|
||||||
|
@Mock private lateinit var recSubtitleMock2: TextView
|
||||||
|
@Mock private lateinit var recSubtitleMock3: TextView
|
||||||
@Mock private lateinit var coverItem: ImageView
|
@Mock private lateinit var coverItem: ImageView
|
||||||
private lateinit var coverItem1: ImageView
|
private lateinit var coverItem1: ImageView
|
||||||
private lateinit var coverItem2: ImageView
|
private lateinit var coverItem2: ImageView
|
||||||
@@ -2081,6 +2088,10 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
whenever(recommendationViewHolder.cardTitle).thenReturn(recCardTitle)
|
whenever(recommendationViewHolder.cardTitle).thenReturn(recCardTitle)
|
||||||
whenever(recommendationViewHolder.mediaCoverItems)
|
whenever(recommendationViewHolder.mediaCoverItems)
|
||||||
.thenReturn(listOf(coverItem, coverItem, coverItem))
|
.thenReturn(listOf(coverItem, coverItem, coverItem))
|
||||||
|
whenever(recommendationViewHolder.mediaProgressBars)
|
||||||
|
.thenReturn(listOf(recProgressBar1, recProgressBar2, recProgressBar3))
|
||||||
|
whenever(recommendationViewHolder.mediaSubtitles)
|
||||||
|
.thenReturn(listOf(recSubtitleMock1, recSubtitleMock2, recSubtitleMock3))
|
||||||
|
|
||||||
val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
|
val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
|
||||||
val canvas = Canvas(bmp)
|
val canvas = Canvas(bmp)
|
||||||
@@ -2118,6 +2129,65 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
verify(coverItem, times(3)).setImageDrawable(any(Drawable::class.java))
|
verify(coverItem, times(3)).setImageDrawable(any(Drawable::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun bindRecommendationWithProgressBars() {
|
||||||
|
fakeFeatureFlag.set(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE, true)
|
||||||
|
whenever(recommendationViewHolder.mediaAppIcons)
|
||||||
|
.thenReturn(listOf(recAppIconItem, recAppIconItem, recAppIconItem))
|
||||||
|
whenever(recommendationViewHolder.cardTitle).thenReturn(recCardTitle)
|
||||||
|
whenever(recommendationViewHolder.mediaCoverItems)
|
||||||
|
.thenReturn(listOf(coverItem, coverItem, coverItem))
|
||||||
|
whenever(recommendationViewHolder.mediaProgressBars)
|
||||||
|
.thenReturn(listOf(recProgressBar1, recProgressBar2, recProgressBar3))
|
||||||
|
whenever(recommendationViewHolder.mediaSubtitles)
|
||||||
|
.thenReturn(listOf(recSubtitleMock1, recSubtitleMock2, recSubtitleMock3))
|
||||||
|
|
||||||
|
val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
|
||||||
|
val canvas = Canvas(bmp)
|
||||||
|
canvas.drawColor(Color.RED)
|
||||||
|
val albumArt = Icon.createWithBitmap(bmp)
|
||||||
|
val bundle =
|
||||||
|
Bundle().apply {
|
||||||
|
putInt(
|
||||||
|
MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS,
|
||||||
|
MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED
|
||||||
|
)
|
||||||
|
putDouble(MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.5)
|
||||||
|
}
|
||||||
|
val data =
|
||||||
|
smartspaceData.copy(
|
||||||
|
recommendations =
|
||||||
|
listOf(
|
||||||
|
SmartspaceAction.Builder("id1", "title1")
|
||||||
|
.setSubtitle("subtitle1")
|
||||||
|
.setIcon(albumArt)
|
||||||
|
.setExtras(bundle)
|
||||||
|
.build(),
|
||||||
|
SmartspaceAction.Builder("id2", "title2")
|
||||||
|
.setSubtitle("subtitle1")
|
||||||
|
.setIcon(albumArt)
|
||||||
|
.setExtras(Bundle.EMPTY)
|
||||||
|
.build(),
|
||||||
|
SmartspaceAction.Builder("id3", "title3")
|
||||||
|
.setSubtitle("subtitle1")
|
||||||
|
.setIcon(albumArt)
|
||||||
|
.setExtras(Bundle.EMPTY)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
player.attachRecommendation(recommendationViewHolder)
|
||||||
|
player.bindRecommendation(data)
|
||||||
|
|
||||||
|
verify(recProgressBar1).setProgress(50)
|
||||||
|
verify(recProgressBar1).visibility = View.VISIBLE
|
||||||
|
verify(recProgressBar2).visibility = View.GONE
|
||||||
|
verify(recProgressBar3).visibility = View.GONE
|
||||||
|
verify(recSubtitleMock1).visibility = View.GONE
|
||||||
|
verify(recSubtitleMock2).visibility = View.VISIBLE
|
||||||
|
verify(recSubtitleMock3).visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun onButtonClick_touchRippleFlagEnabled_playsTouchRipple() {
|
fun onButtonClick_touchRippleFlagEnabled_playsTouchRipple() {
|
||||||
fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
|
fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
|
||||||
|
|||||||
Reference in New Issue
Block a user