[Android] Improve miniplayer / bottombar behavior compatibility

Nicolas Pomepuy git at videolan.org
Thu Apr 16 15:43:37 CEST 2020


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Wed Apr  8 09:14:47 2020 +0200| [52d2c01b909bd2ef523e7a4a8e5ab548693a4444] | committer: Nicolas Pomepuy

Improve miniplayer / bottombar behavior compatibility

> https://code.videolan.org/videolan/vlc-android/commit/52d2c01b909bd2ef523e7a4a8e5ab548693a4444
---

 .../vlc/gui/AudioPlayerContainerActivity.kt        | 37 ++++++++++++++++++++--
 .../vlc/gui/helpers/BottomNavigationBehavior.kt    | 17 ++++++++--
 .../src/org/videolan/vlc/gui/helpers/UiTools.kt    |  9 ++++++
 3 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/application/vlc-android/src/org/videolan/vlc/gui/AudioPlayerContainerActivity.kt b/application/vlc-android/src/org/videolan/vlc/gui/AudioPlayerContainerActivity.kt
index cc8163d8c..8ce447642 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/AudioPlayerContainerActivity.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/AudioPlayerContainerActivity.kt
@@ -58,8 +58,10 @@ import org.videolan.tools.*
 import org.videolan.vlc.*
 import org.videolan.vlc.gui.audio.AudioPlayer
 import org.videolan.vlc.gui.browser.StorageBrowserFragment
+import org.videolan.vlc.gui.helpers.BottomNavigationBehavior
 import org.videolan.vlc.gui.helpers.PlayerBehavior
 import org.videolan.vlc.gui.helpers.UiTools
+import org.videolan.vlc.gui.helpers.getHeightWhenReady
 import org.videolan.vlc.interfaces.IRefreshable
 import org.videolan.vlc.media.PlaylistManager
 
@@ -68,7 +70,7 @@ private const val TAG = "VLC/APCActivity"
 private const val ACTION_DISPLAY_PROGRESSBAR = 1339
 private const val ACTION_SHOW_PLAYER = 1340
 private const val ACTION_HIDE_PLAYER = 1341
-
+private const val BOTTOM_IS_HIDDEN = "bottom_is_hidden"
 @SuppressLint("Registered")
 @ExperimentalCoroutinesApi
 @ObsoleteCoroutinesApi
@@ -105,11 +107,14 @@ open class AudioPlayerContainerActivity : BaseActivity() {
     val isAudioPlayerExpanded: Boolean
         get() = isAudioPlayerReady && playerBehavior.state == STATE_EXPANDED
 
+    var bottomIsHiddden: Boolean = false
+
     override fun onCreate(savedInstanceState: Bundle?) {
         //Init Medialibrary if KO
         if (savedInstanceState != null) {
 
             this.startMedialibrary(firstRun = false, upgrade = false, parse = true)
+            bottomIsHiddden = savedInstanceState.getBoolean(BOTTOM_IS_HIDDEN, false)
         }
         super.onCreate(savedInstanceState)
         volumeControlStream = AudioManager.STREAM_MUSIC
@@ -127,6 +132,13 @@ open class AudioPlayerContainerActivity : BaseActivity() {
         tabLayout = findViewById(R.id.sliding_tabs)
         appBarLayout.setExpanded(true)
         bottomBar = findViewById(R.id.navigation)
+        if (bottomIsHiddden) {
+            bottomBar?.let {
+                val bottomBehavior = BottomNavigationBehavior.from(it) as BottomNavigationBehavior<*>
+                bottomBehavior.isPlayerHidden = true
+                it.getHeightWhenReady { height -> it.translationY = height.toFloat() }
+            }
+        }
         tabLayout?.viewTreeObserver?.addOnGlobalLayoutListener {
             //add a shadow if there are tabs
             if (AndroidUtil.isLolliPopOrLater) appBarLayout.elevation = if (tabLayout?.isVisible() == true) 4.dp.toFloat() else 0.dp.toFloat()
@@ -142,6 +154,8 @@ open class AudioPlayerContainerActivity : BaseActivity() {
         findViewById<View>(R.id.audio_player_stub).visibility = View.VISIBLE
         audioPlayer = supportFragmentManager.findFragmentById(R.id.audio_player) as AudioPlayer
         playerBehavior = from(audioPlayerContainer) as PlayerBehavior<*>
+        val bottomBehavior = bottomBar?.let { BottomNavigationBehavior.from(it) as BottomNavigationBehavior<*> }
+                ?: null
         playerBehavior.peekHeight = resources.getDimensionPixelSize(R.dimen.player_peek_height)
         playerBehavior.addBottomSheetCallback(object : BottomSheetCallback() {
             override fun onSlide(bottomSheet: View, slideOffset: Float) {
@@ -152,13 +166,30 @@ open class AudioPlayerContainerActivity : BaseActivity() {
                 onPlayerStateChanged(bottomSheet, newState)
                 audioPlayer.onStateChanged(newState)
                 if (newState == STATE_COLLAPSED || newState == STATE_HIDDEN) removeTipViewIfDisplayed()
-                if (newState == STATE_DRAGGING) bottomBar?.animate()?.translationY(bottomBar?.height?.toFloat()
-                        ?: 0F)
+                bottomBehavior?.let { bottomBehavior ->
+                    bottomBar?.let { bottomBar ->
+                        if (newState == STATE_DRAGGING) {
+                            bottomBehavior.animateBarVisibility(bottomBar, false)
+                            bottomBehavior.isPlayerHidden = true
+                        }
+                        if (newState == STATE_COLLAPSED) {
+                            bottomBehavior.animateBarVisibility(bottomBar, true)
+                            bottomBehavior.isPlayerHidden = false
+                        }
+                    }
+                }
+
             }
         })
         showTipViewIfNeeded(R.id.audio_player_tips, PREF_AUDIOPLAYER_TIPS_SHOWN)
     }
 
+    override fun onSaveInstanceState(outState: Bundle) {
+        outState.putBoolean(BOTTOM_IS_HIDDEN, bottomBar?.let { BottomNavigationBehavior.from(it) as BottomNavigationBehavior<*> }?.isPlayerHidden
+                ?: false)
+        super.onSaveInstanceState(outState)
+    }
+
     fun expandAppBar() {
         appBarLayout.setExpanded(true)
     }
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/helpers/BottomNavigationBehavior.kt b/application/vlc-android/src/org/videolan/vlc/gui/helpers/BottomNavigationBehavior.kt
index 8ba765814..761faac73 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/helpers/BottomNavigationBehavior.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/helpers/BottomNavigationBehavior.kt
@@ -46,6 +46,7 @@ class BottomNavigationBehavior<V : View>(context: Context, attrs: AttributeSet)
     private var lastStartedType: Int = 0
     private var offsetAnimator: ValueAnimator? = null
     private var isSnappingEnabled = true
+    var isPlayerHidden = false
     private var player: FrameLayout? = null
 
     override fun onNestedPreScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {
@@ -69,6 +70,7 @@ class BottomNavigationBehavior<V : View>(context: Context, attrs: AttributeSet)
     override fun onStartNestedScroll(
             coordinatorLayout: CoordinatorLayout, child: V, directTargetChild: View, target: View, axes: Int, type: Int
     ): Boolean {
+        if (isPlayerHidden) return false
         if (axes != ViewCompat.SCROLL_AXIS_VERTICAL)
             return false
 
@@ -123,7 +125,9 @@ class BottomNavigationBehavior<V : View>(context: Context, attrs: AttributeSet)
         }
     }
 
-    private fun animateBarVisibility(child: View, isVisible: Boolean) {
+    fun animateBarVisibility(child: View, isVisible: Boolean) {
+        val targetTranslation = if (isVisible) 0f else child.height.toFloat()
+        if (child.translationY == targetTranslation) return
         if (offsetAnimator == null) {
             offsetAnimator = ValueAnimator().apply {
                 interpolator = DecelerateInterpolator()
@@ -139,8 +143,17 @@ class BottomNavigationBehavior<V : View>(context: Context, attrs: AttributeSet)
             offsetAnimator?.cancel()
         }
 
-        val targetTranslation = if (isVisible) 0f else child.height.toFloat()
         offsetAnimator?.setFloatValues(child.translationY, targetTranslation)
         offsetAnimator?.start()
     }
+
+    companion object {
+        fun <V : View> from(view: V): BottomNavigationBehavior<V>? {
+            val params = view.layoutParams
+            require(params is CoordinatorLayout.LayoutParams) { "The view is not a child of CoordinatorLayout" }
+            val behavior = params.behavior
+            require(behavior is BottomNavigationBehavior<*>) { "The view is not associated with BottomNavigationBehavior" }
+            return behavior as BottomNavigationBehavior<V>?
+        }
+    }
 }
\ No newline at end of file
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt b/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
index e4b9e88a3..37b06a7b1 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
@@ -671,3 +671,12 @@ fun getTvIconRes(mediaLibraryItem: MediaLibraryItem) = when (mediaLibraryItem.it
     }
     else -> R.drawable.ic_browser_unknown_big_normal
 }
+
+fun View.getHeightWhenReady(listener: (height: Int) -> Unit) {
+    viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
+        override fun onGlobalLayout() {
+            listener(height)
+            viewTreeObserver.removeOnGlobalLayoutListener(this)
+        }
+    })
+}



More information about the Android mailing list