Skip to main content
Version: 1.2.0

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 Pagers 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)
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)
}
}
Last updated on