#android #kotlin #android-fragments #android-viewpager2
Вопрос:
Я пытаюсь динамически добавлять больше фрагментов в свой ViewPager2, однако, когда я вызываю adapter.add(MyNewFragment, position)
2 вещи, происходит, если я использую notifyDataSetChange()
не отображается фрагмент, но если я помещаю notifyItemInserted(position)
отображается, но приложение вылетает с java.lang.IllegalStateException: Fragment already added
.
Это мой класс адаптера:
class ViewPagerAdapter(
list: MutableList<Fragment>,
fm: FragmentManager,
lifecycle: Lifecycle,
//fragmentActivity: FragmentActivity
) : FragmentStateAdapter(fm, lifecycle) {
var fragmentList = list
override fun getItemCount(): Int {
return fragmentList.size
}
fun addScreen(fragment: Fragment, position: Int) {
if(!fragmentList.contains(fragment)){
fragmentList.add(position, fragment)
//notifyItemInserted(position)
notifyDataSetChanged()
}
}
override fun createFragment(position: Int): Fragment {
return fragmentList[position]
}
// I tried to use these methods that I saw here but then the viewpager is totally blank and does not load anything or do the same Fragment already added error.
/* override fun getItemId(position: Int): Long {
return fragmentList[position].id.toLong()
}
override fun containsItem(itemId: Long): Boolean = fragmentList.any { it.id.toLong() == itemId }*/
}
А это мой экран, на котором находится видоискатель:
@AndroidEntryPoint
class ViewPagerScreen : Fragment() {
//...
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
if (!::savedViewInstance.isInitialized) {
_binding = FragmentViewPagerScreenBinding.inflate(inflater, container, false)
//....
savedViewInstance = binding.root
}
binding.viewPager.isSaveEnabled = false
return savedViewInstance
}
fun addNewScreen(){
adapter.addScreen(NewFragment(), binding.viewPager.currentItem 1)
}
private fun initViewPager() {
binding.viewPager.offscreenPageLimit = 2
binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
}
})
adapter = ViewPagerAdapterByFragments(
mutableListOf(FirstScreen(), SecondScreen(), ThirdScreen()),
this@ViewPagerScreen.childFragmentManager,
lifecycle
)
binding.viewPager.adapter = adapter
binding.viewPager.isUserInputEnabled = false
}
}
Комментарии:
1. внутри
createFragment
метода вы не создаете НОВЫЙ фрагмент, вы предоставляете существующий из массива. попробуйте написать этот метод правильно, создайте новый фрагмент в этом методе прямо2. Большое спасибо!! Теперь это работает как заклинание 😀
Ответ №1:
Я думаю, что решил проблему, спасибо @snachmsm за то, что указал мне, где искать.
То, что я сделал, было довольно просто, мне нужно было только изменить параметр list: MutableList<Fragment>
на list:MutableList<Pair<String,Fragment>>
String
«мой fragmentId
«. Затем по методу createFragment
возвращаем новый фрагмент базы на мой fragmentId
.
Вот сам код:
override fun createFragment(position: Int): Fragment {
return when (fragmentList!![position]!!.first) {
"firstScreen" -> return FirstScreen()
"secondScreen" ->return SecondScreen()
"thirdScreen" ->return ThirdScreen()
"newScreen" -> return NewScreen()
else -> AnotherScreen()
}
}
Также мое addScreenMethod()
сейчас выглядит так:
fun addScreen(newfragment: Pair<String, Fragment>, position: Int) {
val result = fragmentList.find {
it.first == newfragment.first
}
if (result == null) {
fragmentList.add(position, newfragment)
notifyItemInserted(position)
}
}