Trying to use Android's Data Binding to adapter for a ViewPager (controls slidable Fragments).
FooPagerAdapter.kt:
class FooPagerAdapter(fm: Fragmentmanager, private val mFragments: List<BarFragment>) : FragmentStatePagerAdapter(fm) {
override fun getItem(position: int): Fragment {
return mFragments(position)
}
override fun getCount(): Int {
return mFragments.size
}
}
If done from the Activity, it would look like:
..
mFooViewPager.adapter = FooPagerAdapter(fragmentFamanager, fragmentsList)
..
Question:
Now how does one transfer adapter functionality to the binding file to update fragments ViewPager using Data Binding?
Edit:
As I understand it has to be something like this.
activity_foo.xml:
<android.support.v4.view.ViewPager
..
app:fragments"${viewModel.fragments}"/>
And then in a FooViewModel.kt:
fun getFragments(): LiveData<List<BarFragment>>? = mFragments
companion object {
@BindingAdapter("bind:fragments")
fun setAdapter(pager: ViewPager, adapter: BarPagerAdapter) {
pager.adapter = adapter
}
}
Edit2:
Decided to use a ViewModel directly (without binding) to set ViewPager's adapter.
activity_foo.xml:
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.foo.bar.viewmodels.FooViewModel"/>
</data>
..
<android.support.v4.view.ViewPager
..
app:adapter="%{viewModel.adapter}"/>
FooViewModel.kt:
class FooViewModel(application: Application) : AndroidViewModel(application) {
..
fun setAdapter(pager: ViewPager, fragments:List<PeriodFragment>) {
pager.adapter = PeriodsPagerAdapter(mFragmentManager!!, periods)
}
Getting:
Error:...layout\activity_foo.xml:39 attribute 'com.foo.bar:adapter' not found
A @BindingAdapter should be static in Java, thus be annotated with @JvmStatic. Additionally you're supposed to skip all namespaces with the binding attributes in the adapter definition. Also the second parameter needs to reference a type you want to set. In your case this is LiveData<List<BarFragment>>. Then you can create the adapter statically.
companion object {
@JvmStatic
@BindingAdapter("fragments")
fun setAdapter(pager: ViewPager, fragments: LiveData<List<BarFragment>>) {
pager.adapter = createAdapterForFragments(fragments)
}
}
But if fragments would be a PagerAdapter, a binding adapter is not necessary at all. As a default implementation the compiler looks for a given setter method for the attribute. So if you use app:adapter, the setAdapter() method will be used automatically. Therefore it should be sufficient to just put this adapter definition in the layout.
<android.support.v4.view.ViewPager
...
app:adapter"@{viewModel.fragments}"/>
I'd suggest to use the latter and setup the adapter with the viewModel not with the data binding.
A little data binding convenience for ViewPager and TabLayout you'll find with ViewPagerDataBinding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With