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:
@@ -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()
|
||||
|
||||
@@ -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") {
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user