Skip to content

Commit 96c380d

Browse files
committed
Issue-810: Fixed an issue causing removed control components to be re-added on load state changes
1 parent 9fcb37a commit 96c380d

File tree

3 files changed

+72
-19
lines changed

3 files changed

+72
-19
lines changed

library/src/main/kotlin/com/devbrackets/android/exomedia/ui/widget/controls/DefaultVideoControls.kt

+60-7
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import android.graphics.drawable.Drawable
55
import android.os.Handler
66
import android.os.Looper
77
import android.util.AttributeSet
8-
import android.util.SparseBooleanArray
98
import android.view.View
109
import android.widget.ImageButton
1110
import android.widget.ProgressBar
1211
import android.widget.RelativeLayout
1312
import android.widget.SeekBar
1413
import android.widget.TextView
1514
import androidx.annotation.ColorRes
15+
import androidx.annotation.IdRes
1616
import androidx.annotation.IntRange
1717
import androidx.annotation.LayoutRes
1818
import androidx.media3.common.Timeline
@@ -67,8 +67,7 @@ abstract class DefaultVideoControls : RelativeLayout, VideoControls, OnTimelineC
6767
var visibilityListener: VideoControlsVisibilityListener? = null
6868

6969
protected var internalListener = InternalListener()
70-
71-
protected var enabledViews = SparseBooleanArray()
70+
protected val configuration = Configuration()
7271

7372
/**
7473
* The delay in milliseconds to wait to start the hide animation
@@ -179,7 +178,7 @@ abstract class DefaultVideoControls : RelativeLayout, VideoControls, OnTimelineC
179178
timeline.getWindow(timeline.windowCount -1, window)
180179
if (window.isPlaceholder) {
181180
return onTimelineStyleUpdated(TimelineStyle.UNKNOWN)
182-
} else if (!window.isLive()) {
181+
} else if (!window.isLive) {
183182
return onTimelineStyleUpdated(TimelineStyle.ON_DEMAND)
184183
}
185184

@@ -190,7 +189,7 @@ abstract class DefaultVideoControls : RelativeLayout, VideoControls, OnTimelineC
190189
return onTimelineStyleUpdated(TimelineStyle.UNKNOWN)
191190
}
192191

193-
val rollingStart = window.isDynamic || window.isLive()
192+
val rollingStart = window.isDynamic || window.isLive
194193
val style = when {
195194
rollingStart -> TimelineStyle.LIVE
196195
else -> TimelineStyle.EVENT
@@ -419,7 +418,7 @@ abstract class DefaultVideoControls : RelativeLayout, VideoControls, OnTimelineC
419418
*/
420419
fun setPreviousButtonEnabled(enabled: Boolean) {
421420
previousButton.isEnabled = enabled
422-
enabledViews.put(R.id.exomedia_controls_previous_btn, enabled)
421+
configuration.setEnabled(R.id.exomedia_controls_previous_btn, enabled)
423422
}
424423

425424
/**
@@ -430,7 +429,7 @@ abstract class DefaultVideoControls : RelativeLayout, VideoControls, OnTimelineC
430429
*/
431430
fun setNextButtonEnabled(enabled: Boolean) {
432431
nextButton.isEnabled = enabled
433-
enabledViews.put(R.id.exomedia_controls_next_btn, enabled)
432+
configuration.setEnabled(R.id.exomedia_controls_next_btn, enabled)
434433
}
435434

436435
/**
@@ -471,6 +470,7 @@ abstract class DefaultVideoControls : RelativeLayout, VideoControls, OnTimelineC
471470
*/
472471
fun setPreviousButtonRemoved(removed: Boolean) {
473472
previousButton.visibility = if (removed) View.GONE else View.VISIBLE
473+
configuration.setRemoved(R.id.exomedia_controls_previous_btn, removed)
474474
}
475475

476476
/**
@@ -481,6 +481,7 @@ abstract class DefaultVideoControls : RelativeLayout, VideoControls, OnTimelineC
481481
*/
482482
fun setNextButtonRemoved(removed: Boolean) {
483483
nextButton.visibility = if (removed) View.GONE else View.VISIBLE
484+
configuration.setRemoved(R.id.exomedia_controls_next_btn, removed)
484485
}
485486

486487
/**
@@ -739,6 +740,58 @@ abstract class DefaultVideoControls : RelativeLayout, VideoControls, OnTimelineC
739740
}
740741
}
741742

743+
// TODO: rename to something a bit better...
744+
protected class Configuration {
745+
private val itemConfigs = mutableMapOf<Int, ItemConfig>()
746+
747+
fun isEnabled(@IdRes id: Int): Boolean {
748+
return getViewConfiguration(id)?.enabled ?: true
749+
}
750+
751+
fun setEnabled(@IdRes id: Int, enabled: Boolean) {
752+
updateViewConfiguration(id) {
753+
it.copy(enabled = enabled)
754+
}
755+
}
756+
757+
fun isRemoved(@IdRes id: Int): Boolean {
758+
return getViewConfiguration(id)?.removed ?: false
759+
}
760+
761+
fun setRemoved(@IdRes id: Int, removed: Boolean) {
762+
updateViewConfiguration(id) {
763+
it.copy(removed = removed)
764+
}
765+
}
766+
767+
/**
768+
* Helper function to get the Visibility value for the view with [id]
769+
*/
770+
fun visibility(@IdRes id: Int): Int {
771+
return if (isRemoved(id)) View.GONE else View.VISIBLE
772+
}
773+
774+
private fun getViewConfiguration(@IdRes id: Int): ItemConfig? {
775+
return synchronized(this) {
776+
itemConfigs[id]
777+
}
778+
}
779+
780+
private fun updateViewConfiguration(@IdRes id: Int, action: (ItemConfig) -> ItemConfig?) {
781+
synchronized(this) {
782+
when (val newConfig = action(itemConfigs[id] ?: ItemConfig())) {
783+
null -> itemConfigs.remove(id)
784+
else -> itemConfigs[id] = newConfig
785+
}
786+
}
787+
}
788+
789+
private data class ItemConfig(
790+
val enabled: Boolean = true,
791+
val removed: Boolean = false
792+
)
793+
}
794+
742795
enum class LoadState {
743796
/**
744797
* Occurs when the media content is being prepared for playback. This

library/src/main/kotlin/com/devbrackets/android/exomedia/ui/widget/controls/VideoControlsMobile.kt

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import android.view.ViewGroup
1010
import android.widget.LinearLayout
1111
import android.widget.SeekBar
1212
import com.devbrackets.android.exomedia.R
13-
import java.util.*
13+
import java.util.LinkedList
1414

1515
/**
1616
* Provides playback controls for the [com.devbrackets.android.exomedia.ui.widget.VideoView]
@@ -130,11 +130,11 @@ class VideoControlsMobile : DefaultVideoControls {
130130
playPauseButton.visibility = View.VISIBLE
131131
playPauseButton.isEnabled = true
132132

133-
previousButton.visibility = View.VISIBLE
134-
previousButton.isEnabled = enabledViews.get(R.id.exomedia_controls_previous_btn, true)
133+
previousButton.visibility = configuration.visibility(R.id.exomedia_controls_previous_btn)
134+
previousButton.isEnabled = configuration.isEnabled(R.id.exomedia_controls_previous_btn)
135135

136-
nextButton.visibility = View.VISIBLE
137-
nextButton.isEnabled = enabledViews.get(R.id.exomedia_controls_next_btn, true)
136+
nextButton.visibility = configuration.visibility(R.id.exomedia_controls_next_btn)
137+
nextButton.isEnabled = configuration.isEnabled(R.id.exomedia_controls_next_btn)
138138

139139
extraViewsContainer.visibility = View.VISIBLE
140140

library/src/main/kotlin/com/devbrackets/android/exomedia/ui/widget/controls/VideoControlsTv.kt

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ import android.util.AttributeSet
55
import android.view.KeyEvent
66
import android.view.View
77
import android.view.ViewGroup
8-
import android.widget.*
8+
import android.widget.LinearLayout
9+
import android.widget.SeekBar
910
import androidx.core.view.forEach
1011
import com.devbrackets.android.exomedia.BuildConfig
1112
import com.devbrackets.android.exomedia.R
1213
import com.devbrackets.android.exomedia.util.view.DelegatedOnKeyListener
1314
import com.devbrackets.android.exomedia.util.view.UnhandledMediaKeyLogger
14-
import java.util.*
15+
import java.util.LinkedList
1516

1617
/**
1718
* Provides playback controls for the [com.devbrackets.android.exomedia.ui.widget.VideoView]
@@ -158,11 +159,11 @@ class VideoControlsTv : DefaultVideoControls {
158159
playPauseButton.visibility = View.VISIBLE
159160
playPauseButton.isEnabled = true
160161

161-
previousButton.visibility = View.VISIBLE
162-
previousButton.isEnabled = enabledViews.get(R.id.exomedia_controls_previous_btn, true)
162+
previousButton.visibility = configuration.visibility(R.id.exomedia_controls_previous_btn)
163+
previousButton.isEnabled = configuration.isEnabled(R.id.exomedia_controls_previous_btn)
163164

164-
nextButton.visibility = View.VISIBLE
165-
nextButton.isEnabled = enabledViews.get(R.id.exomedia_controls_next_btn, true)
165+
nextButton.visibility = configuration.visibility(R.id.exomedia_controls_next_btn)
166+
nextButton.isEnabled = configuration.isEnabled(R.id.exomedia_controls_next_btn)
166167

167168
extraViewsContainer.visibility = View.VISIBLE
168169

@@ -437,7 +438,6 @@ class VideoControlsTv : DefaultVideoControls {
437438
return seekBy(-FAST_FORWARD_REWIND_AMOUNT)
438439
}
439440

440-
@Suppress("FoldInitializerAndIfToElvis")
441441
private fun seekBy(amountMillis: Long): Boolean {
442442
val view = videoView
443443
if (view == null || !view.isAttachedToWindow) {

0 commit comments

Comments
 (0)