У меня есть пользовательские ViewPager
и PagerAdapter
, которые загружают элементы внутри instantiateItem
. Он работает нормально, если я инициализирую его в первый раз с заданным списком элементов.
Но когда я вызываю refre sh в списке, я хочу заполнить адаптер новым (совершенно другим) списком после При вызове viewPager.adapter?.notifyDataSetChanged()
PagerAdapter перестает работать должным образом, и эти элементы являются пустыми страницами без содержимого, и я могу пролистывать их в пользовательском интерфейсе.
PageScreen
не Fragment
. Это просто контейнер ViewGroup
, который раздувает макет и устанавливает значения вне указанного элемента c. Он похож на ViewHolder
+ Binder
в RecyclerView
.
Также instatiateItem()
вызывается только один раз, когда я добавляю новый список и вызываю notifyDataSetChanged()
. Вначале он называется 3 элемента, что составляет PageScreen
элементов в первом списке.
//init
val pages = mutableListOf<PageScreen>()
pages.add(PageScreen(activity, app, itemJs1, onClick = {onItemClicked(itemJs1.id)}))
pages.add(PageScreen(activity, app, itemJs2, onClick = {onItemClicked(itemJs2.id)}))
pages.add(PageScreen(activity, app, itemJs3, onClick = {onItemClicked(itemJs3.id)}))
swipePager.adapter = CustomPagerAdapter(pages).also { it.notifyDataSetChanged() }
...
//on refresh after API call
pages.clear()
contentList.forEach{item-> pages.add(PageScreen(activity, app, item, onClick = {onItemClicked(item.id)}))}
(swipePager.adapter as? CustomPagerAdapter)?.notifyDataSetChanged()
Также пробовал (тот же результат):
//on refresh after API call
val newPages = mutableListOf<PageScreen>()
contentList.forEach{item-> newPages.add(PageScreen(activity, app, item, onClick = {onItemClicked(item.id)}))}
swipePager.adapter = CustomPagerAdapter(newPages).also { it.notifyDataSetChanged() }
Адаптер:
class CustomPagerAdapter(private var pageList: MutableList<PageScreen>) : PagerAdapter() {
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view == `object`
}
override fun getCount(): Int {
return pageList.size
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
container.removeView(`object` as View)
}
override fun instantiateItem(container: ViewGroup, position: Int): View {
val layout = pageList[position].getScreen(container)
container.addView(layout)
return layout
}
}
Также я попытался правильно обновить элементы sh (я ожидаю, что это делается внутри PagerAdapter и ViewPager, когда я вызываю notifyDataSetChanged()
), удаляя их из ViewPager contentView и вызывая instantiateItem()
для каждого элемента . Но результат тот же, что и выше. Теперь каждая страница была пустой. Функция ниже добавлена к CustomPagerAdapter
.
fun refreshItems(vp: ViewPager, data: MutableList<PageScreen>){
pageList.apply {
forEachIndexed{pos, item->
item.screenView?.let { sv->
destroyItem(vp, pos, sv)
}
}
clear()
addAll(data)
forEachIndexed { pos, _ -> instantiateItem(vp, pos) }
}
notifyDataSetChanged()
}
ОБНОВЛЕНИЕ: Мне удалось «исправить» это, установив высоту ViewPager на фиксированное значение вместо WRAP_CONTENT
, но это не решение. Мне нужен ViewPager с динамической c высотой, потому что некоторые из его дочерних элементов могут иметь разную высоту + установка чего-то в stati c не является хорошим подходом в Android. Некоторые телефоны с квадратными дисплеями тогда могли обрезать страницу.
Когда я заменил все элементы, эти «пустые» страницы были элементами с высотой 0 пикселей и шириной 0 пикселей по неизвестной причине.
Если я заменил высоту ViewPager на значение dp, он "заработал". Но когда я заменил эти представления, первый элемент всегда был пустым. но когда я прокручивал к третьему и обратно к первому, элемент был там по какой-то причине.
Также у меня нет проблемы с высотой. У меня есть функция внутри ViewPager, которая устанавливает высоту на основе самого высокого ребенка в списке. Он работает, если список имеет значение c, но теперь он не работает, поскольку я обновляю sh это.