Reputation: 7321
I have a Viewpager2
set up with Tablyout
via TabLayoutMediator
. Adapter for the Viewpager2
is RecyclerView.Adapter
I am initializing Viewpager2
and Tablayout
, and loading image into tabs as below:
myViewPager.apply {
offscreenPageLimit = 6
adapter = myRecycerViewAdapter
}
TabLayoutMediator(myTabLayout, myViewPager) { tab, position ->
val tabView: View =
LayoutInflater.from(context).inflate(R.layout.tab_magazine_preview, null)
Glide.with(context)
.load(urls[position])
.into(tabView.imageView)
tab.customView = tabView
}.attach()
Now this implementation creates all tabs during initializing and loads all urls
into imageview
in tabs. This is resource consuming approach as user might not swipe to all the way till the end. And If I have huge list of urls, this is even more resource consuming.
There is nice feature of Viewpager2
- offscreenPageLimit
which helps to load only certain amount of adjacent pages. Can I have similar feature for Tablayout?
I want to load only ceratin amount of adjacent tabs at time as user swipes.
Upvotes: 0
Views: 1086
Reputation: 641
You can detect swipe gestures on TabLayout
using View.OnScrollChangeListener
and then load images, but quick test showed me that you need to load images manually on initialization for visible tabs, because there was no scrolling.
tabLayout.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
if (v is TabLayout) {
val scrollBounds = Rect()
v.getHitRect(scrollBounds)
for (i in 0 until v.tabCount) {
if (v.getTabAt(i)!!.view.getLocalVisibleRect(scrollBounds)) {
Log.i("!!!!!!!!!!", "child visible at: " + i);
// check if image is not loaded/loading and load
} else {
Log.i("!!!!!!!!!!", "child invisible: " + i);
}
}
}
}
OLD ANSWER. I misunderstood the question:
You can do that by listening for ViewPager2.OnPageChangeCallback
and telling desired fragments to load their images based on page position.
Make sure your page fragment implements interface that allows it to load image:
interface ILoadImage {
fun loadImage()
}
class MyPageFragment : Fragment(), ILoadImage {
private var isImageLoaded = false
override fun loadImage() {
if (isImageLoaded) return
/*
... load image
*/
isImageLoaded = true
}
}
Then inside your myRecycerViewAdapter
create function that will accept selected page position and update fragments
class MyRecycerViewAdapter /* ... */ {
val fragments: List<ILoadImage> = //...
fun loadImagesForPosition(position: Int) {
fragments[position].loadImage()
// also you can load images for next or prev fragments
}
}
And finally listen for OnPageChangedCallback
and tell adapter to update fragments
myViewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
myRecycerViewAdapter.loadImagesForPosition(position)
}
})
Upvotes: 1