Pager
A common use-case for video playback in modern applications is showing videos in a ViewPager
fashion,
where videos occupy the full width/height of the container and can be navigated through swipe gestures.
We provide special player implementations that inherit the Pager
interface. All pagers extend
Player
as well, so you can use all the player APIs that you are already familiar
with.
With respect to a simple Playlist
+ Player
setup (as described here), the pager will:
- ensure the best performance with respect to video preloading
- automatically care about video playback (stop, play, pause according to video position)
- automatically react to changes in the playlist contents
- offer extra features on top of the base
Player
Transitions
All Pager
s offer animated transitions between videos. These transitions happen when the users
swipes on screen, but also on regular navigation (e.g. when calling Pager.navigator.next()
).
Configuring transitions is done through two parameters called TransitionType
and TransitionControl
:
val pager: Pager = ...
// Transition is off, and it can't be controlled through gestures.
pager.setTransition(TransitionType.None(), TransitionControl.NONE)
// Simple horizontal transition, which can be controlled through horizontal swipes.
pager.setTransition(TransitionType.Horizontal(), TransitionControl.SWIPE_HORIZONTAL)
// Simple vertical transition, which can be controlled through vertical swipes.
pager.setTransition(TransitionType.Vertical(), TransitionControl.SWIPE_VERTICAL)
Note that transition type and control can be retrieved at runtime using properties with the same name.
You can also specify the desired transition when using PagerOptions
(see below).
Item overlays
Pager components show each video in a separate View
. Sometimes it is desirable to overlay extra elements
on each video view, for example buttons to like, flag or comment. This is possible using the Pager.itemOverlay
option:
val pager: Pager = ...
pager.itemOverlay(R.layout.item_overlay)
The given layout will be inflated as many times as needed and displayed over each video - when the
user swipes, the itemOverlay
contents will swipe together. In addition, the inflated view can implement the
ItemOverlay
interface:
interface ItemOverlay {
fun bind(video: Video, position: Int)
fun unbind()
}
If you do, the bind/unbind functions will be invoked by the Pager
so that you can bind the UI to
the specific video contents or metadata. Note that you can also specify itemOverlay
using PagerOptions
instead of the setter (see below).
Implementations
We offer three pager implementations, just like we do with regular players.
PagerController
A PagerController
is the low level implementation that, unlike the others, is detached from
the UI. You will typically hold the controller instance in a ViewModel. Optionally,
for perfect state restoration during configuration changes, we also recommend that you use Android's
SavedStateHandle
and pass it to the controller constructor.
class PagerViewModel(state: SavedStateHandle) : ViewModel() {
val pager = PagerController(state)
override fun onCleared() {
super.onCleared()
pager.release()
}
}
As you can see, the PagerController
must be released when you're done with it.
In order to show the UI and start using the viewer, you must also call one of the bind
methods
as soon as you have a view container. For example, with a fragment:
class PagerFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.pager.bind(this, view.findViewById(R.id.container))
}
}
By passing in the fragment instance, the controller will use the fragment lifecycle to avoid memory leaks, so that there's no need to unbind.
PagerFragment
The PagerFragment
is a fragment implemented exactly as described above. It is
the recommended implementation as it is very easy to use - no need to release or bind UI,
because the fragment owns the views.
You can customize the fragment after it is attached or when creating it, thanks to
the PagerOptions
class:
val options = PagerOptions.build {
aspectMode(AspectMode.CENTER_INSIDE)
playbackQuality(Quality.AUTO)
mute(false)
loop(true)
transition(TransitionType.Horizontal(), TransitionControl.SWIPE_HORIZONTAL)
useHls(true)
overlay(R.layout.custom_overlay)
itemOverlay(R.layout.custom_item_overlay)
}
val fragment = PagerOptions.newInstance(options)
PagerView
The PagerView
is a view that holds a controller, to be used for codebases that do not use
fragments at all. Just like the controller, you must pass a fragment / activity / lifecycle with bind()
to use it.
class PagerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.pager_view)
val view = findViewById<PagerView>(R.id.player)
view.bind(this) // necessary!
val playlist = intent.getParcelableExtra<Playlist>("playlist")!!
view.set(playlist, play = true)
}
}