Merge "Slide transition from the media reco card to the active media player after a media reco is tapped." into sc-dev

This commit is contained in:
Cecilia Hong
2021-05-06 21:23:15 +00:00
committed by Android (Google) Code Review
3 changed files with 50 additions and 16 deletions

View File

@@ -115,6 +115,7 @@ class MediaCarouselController @Inject constructor(
private var needsReordering: Boolean = false
private var keysNeedRemoval = mutableSetOf<String>()
private var bgColor = getBackgroundColor()
private var shouldScrollToActivePlayer: Boolean = false
private var isRtl: Boolean = false
set(value) {
if (value != field) {
@@ -271,6 +272,15 @@ class MediaCarouselController @Inject constructor(
}
}
mediaCarouselScrollHandler.onPlayersChanged()
// Automatically scroll to the active player if needed
if (shouldScrollToActivePlayer) {
shouldScrollToActivePlayer = false
val activeMediaIndex = MediaPlayerData.getActiveMediaIndex()
if (activeMediaIndex != -1) {
mediaCarouselScrollHandler.scrollToActivePlayer(activeMediaIndex)
}
}
}
private fun addOrUpdatePlayer(key: String, oldKey: String?, data: MediaData) {
@@ -322,8 +332,8 @@ class MediaCarouselController @Inject constructor(
val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)
newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp)
newRecs.bindRecommendation(data, bgColor)
MediaPlayerData.addMediaPlayer(key, newRecs)
newRecs.bindRecommendation(data, bgColor, { v -> shouldScrollToActivePlayer = true })
MediaPlayerData.addMediaRecommendation(key, newRecs)
updatePlayerToState(newRecs, noAnimation = true)
reorderAllPlayers()
updatePageIndicator()
@@ -593,7 +603,7 @@ class MediaCarouselController @Inject constructor(
@VisibleForTesting
internal object MediaPlayerData {
private val EMPTY = MediaData(-1, false, 0, null, null, null, null, null,
emptyList(), emptyList(), "INVALID", null, null, null, true, null)
emptyList(), emptyList(), "INVALID", null, null, null, false, null)
private data class MediaSortKey(
// Is Smartspace media recommendation. When the Smartspace media is present, it should
@@ -620,7 +630,7 @@ internal object MediaPlayerData {
mediaPlayers.put(sortKey, player)
}
fun addMediaPlayer(key: String, player: MediaControlPanel) {
fun addMediaRecommendation(key: String, player: MediaControlPanel) {
removeMediaPlayer(key)
val sortKey = MediaSortKey(isSsMediaRec = true, EMPTY, System.currentTimeMillis())
mediaData.put(key, sortKey)
@@ -643,6 +653,16 @@ internal object MediaPlayerData {
fun players() = mediaPlayers.values
/** Returns the index of the first non-timeout media. */
fun getActiveMediaIndex(): Int {
mediaPlayers.entries.forEachIndexed { index, e ->
if (e.key.data.active) {
return index
}
}
return -1
}
@VisibleForTesting
fun clear() {
mediaData.clear()

View File

@@ -38,6 +38,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor
private const val FLING_SLOP = 1000000
private const val DISMISS_DELAY = 100L
private const val SCROLL_DELAY = 100L
private const val RUBBERBAND_FACTOR = 0.2f
private const val SETTINGS_BUTTON_TRANSLATION_FRACTION = 0.3f
@@ -100,10 +101,11 @@ class MediaCarouselScrollHandler(
private lateinit var settingsButton: View
/**
* What's the currently active player index?
* What's the currently visible player index?
*/
var activeMediaIndex: Int = 0
var visibleMediaIndex: Int = 0
private set
/**
* How much are we scrolled into the current media?
*/
@@ -129,7 +131,7 @@ class MediaCarouselScrollHandler(
field = value
// The player width has changed, let's update the scroll position to make sure
// it's still at the same place
var newRelativeScroll = activeMediaIndex * playerWidthPlusPadding
var newRelativeScroll = visibleMediaIndex * playerWidthPlusPadding
if (scrollIntoCurrentMedia > playerWidthPlusPadding) {
newRelativeScroll += playerWidthPlusPadding -
(scrollIntoCurrentMedia - playerWidthPlusPadding)
@@ -457,12 +459,12 @@ class MediaCarouselScrollHandler(
val wasScrolledIn = scrollIntoCurrentMedia != 0
scrollIntoCurrentMedia = scrollInAmount
val nowScrolledIn = scrollIntoCurrentMedia != 0
if (newIndex != activeMediaIndex || wasScrolledIn != nowScrolledIn) {
activeMediaIndex = newIndex
if (newIndex != visibleMediaIndex || wasScrolledIn != nowScrolledIn) {
visibleMediaIndex = newIndex
closeGuts()
updatePlayerVisibilities()
}
val relativeLocation = activeMediaIndex.toFloat() + if (playerWidthPlusPadding > 0)
val relativeLocation = visibleMediaIndex.toFloat() + if (playerWidthPlusPadding > 0)
scrollInAmount.toFloat() / playerWidthPlusPadding else 0f
// Fix the location, because PageIndicator does not handle RTL internally
val location = if (isRtl) {
@@ -500,7 +502,7 @@ class MediaCarouselScrollHandler(
val scrolledIn = scrollIntoCurrentMedia != 0
for (i in 0 until mediaContent.childCount) {
val view = mediaContent.getChildAt(i)
val visible = (i == activeMediaIndex) || ((i == (activeMediaIndex + 1)) && scrolledIn)
val visible = (i == visibleMediaIndex) || ((i == (visibleMediaIndex + 1)) && scrolledIn)
view.visibility = if (visible) View.VISIBLE else View.INVISIBLE
}
}
@@ -511,12 +513,12 @@ class MediaCarouselScrollHandler(
*/
fun onPrePlayerRemoved(removed: MediaControlPanel) {
val removedIndex = mediaContent.indexOfChild(removed.playerViewHolder?.player)
// If the removed index is less than the activeMediaIndex, then we need to decrement it.
// If the removed index is less than the visibleMediaIndex, then we need to decrement it.
// RTL has no effect on this, because indices are always relative (start-to-end).
// Update the index 'manually' since we won't always get a call to onMediaScrollingChanged
val beforeActive = removedIndex <= activeMediaIndex
val beforeActive = removedIndex <= visibleMediaIndex
if (beforeActive) {
activeMediaIndex = Math.max(0, activeMediaIndex - 1)
visibleMediaIndex = Math.max(0, visibleMediaIndex - 1)
}
// If the removed media item is "left of" the active one (in an absolute sense), we need to
// scroll the view to keep that player in view. This is because scroll position is always
@@ -545,6 +547,17 @@ class MediaCarouselScrollHandler(
scrollView.relativeScrollX = 0
}
fun scrollToActivePlayer(activePlayerIndex: Int) {
var destIndex = activePlayerIndex
destIndex = Math.min(mediaContent.getChildCount() - 1, destIndex)
val view = mediaContent.getChildAt(destIndex)
// We need to post this to wait for the active player becomes visible.
mainExecutor.executeDelayed({
visibleMediaIndex = activePlayerIndex
scrollView.smoothScrollTo(view.left, scrollView.scrollY)
}, SCROLL_DELAY)
}
companion object {
private val CONTENT_TRANSLATION = object : FloatPropertyCompat<MediaCarouselScrollHandler>(
"contentTranslation") {

View File

@@ -462,7 +462,8 @@ public class MediaControlPanel {
/** Bind this recommendation view based on the data given. */
public void bindRecommendation(
@NonNull SmartspaceTarget target,
@NonNull int backgroundColor) {
@NonNull int backgroundColor,
@Nullable View.OnClickListener callback) {
if (mRecommendationViewHolder == null) {
return;
}
@@ -526,7 +527,7 @@ public class MediaControlPanel {
setSmartspaceRecItemOnClickListener(
mediaCoverImageView,
recommendation,
null);
callback);
if (uiComponentIndex < MEDIA_RECOMMENDATION_ITEMS_PER_ROW) {
setVisibleAndAlpha(collapsedSet,