为啥 ViewPager 无限循环不起作用?
Posted
技术标签:
【中文标题】为啥 ViewPager 无限循环不起作用?【英文标题】:Why isn't the ViewPager infinite loop not working?为什么 ViewPager 无限循环不起作用? 【发布时间】:2021-10-28 05:48:47 【问题描述】:所以我有这个轮播项目,它通过 ViewPager 以轮播方式显示一组图片。在达到这一点之前,我已经通过手动将图片和信息放入可变列表来测试 ViewPager 的功能,并且它有效。现在使用来自 API 的信息来做这件事,它似乎不再起作用了。对于控制循环的实际功能,我也没有改变任何东西。
适配器
class CarouselItemAdapter internal constructor (info: MutableList<CarouselItem>,viewPager2: ViewPager2) : ListAdapter<CarouselItem,CarouselItemAdapter.CarouselViewHolder>(DiffCallback)
private val viewPager2: ViewPager2
private var info: MutableList<CarouselItem>
companion object DiffCallback : DiffUtil.ItemCallback<CarouselItem>()
override fun areItemsTheSame(oldItem: CarouselItem, newItem: CarouselItem): Boolean
return oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: CarouselItem, newItem: CarouselItem): Boolean
return oldItem == newItem
init
this.viewPager2 = viewPager2
this.info = info
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): CarouselViewHolder
return CarouselViewHolder(CustomContainerBinding.inflate(
LayoutInflater.from(parent.context),
parent, false))
override fun onBindViewHolder(holder: CarouselViewHolder, position: Int)
holder.bind(getItem(position))
if (position == info.size - 2)
viewPager2.post(runnable)
class CarouselViewHolder(private val binding: CustomContainerBinding) : RecyclerView.ViewHolder(binding.root)
fun bind(item: CarouselItem)
binding.parts = item
binding.executePendingBindings()
private val runnable = Runnable
info.addAll(info)
notifyDataSetChanged()
fun addAll(items: MutableList<CarouselItem>)
info = items
notifyDataSetChanged()
片段
class MainFragment: Fragment()
// private lateinit var manager: RecyclerView.LayoutManager
private lateinit var viewModel: MainFragmentViewModel
private lateinit var viewPager: ViewPager2
private var counter: Int = 0
private var pageChangeCallback: ViewPager2.OnPageChangeCallback? = null
var data: MutableList<CarouselItem> = ArrayList()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View?
val binding: MainFragmentBinding = DataBindingUtil.inflate(
inflater,
R.layout.main_fragment,
container, false)
val mainViewModelFactory = MainFragmentViewModelFactory(requireActivity().application)
viewModel = ViewModelProvider(this, mainViewModelFactory).get(MainFragmentViewModel::class.java)
binding.viewModel = viewModel
viewPager = binding.imageSlider
//
// val data: MutableList<CarouselItem> = ArrayList()
// data.add(CarouselItem(1, "bcw_65", "First"))
// data.add(CarouselItem(2, "bcw_66", "Second"))
// data.add(CarouselItem(3, "bcw_67", "Third"))
// data.add(CarouselItem(4, "bcw_68", "Fourth"))
// data.add(CarouselItem(5, "bcw_69", "Fifth"))
// data.add(CarouselItem(6, "bcw_70", "Sixth"))
// data.add(CarouselItem(2, "bcw_71", "Seventh"))
val adapter = CarouselItemAdapter(data, viewPager)
viewPager.adapter = adapter
viewModel.picInfo.observe(viewLifecycleOwner, Observer
adapter.addAll(data)
adapter.submitList(it)
)
viewPager.clipToPadding = false
viewPager.clipChildren = false
viewPager.offscreenPageLimit = 3
viewPager.getChildAt(0).overScrollMode = RecyclerView.OVER_SCROLL_NEVER
val compositePageTransformer = CompositePageTransformer()
compositePageTransformer.addTransformer(MarginPageTransformer(30))
compositePageTransformer.addTransformer page, position ->
val r = 1 - abs(position)
page.scaleY = 0.85f + r * 0.25f
viewPager.setPageTransformer(compositePageTransformer)
createChannel(
getString(R.string.carousel_notification_id),
getString(R.string.app_name)
)
val notificationManager = ContextCompat.getSystemService(
requireContext(),
NotificationManager::class.java,
) as NotificationManager
//Used to count the number of swipes bing called
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback()
override fun onPageSelected(position: Int)
counter++
binding.counterView.text = counter.toString()
if((counter % 20) == 0)
notificationManager.sendNotification(
requireContext().getText(R.string.swipe_description).toString(), requireContext())
.also pageChangeCallback = it )
return binding.root
//Needed to destroy the pageChangeCallback
override fun onDestroyView()
super.onDestroyView()
viewPager.unregisterOnPageChangeCallback(pageChangeCallback!!)
pageChangeCallback = null
private fun createChannel (channelID: String, channelName: String)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
val notificationChannel = NotificationChannel(
channelID,
channelName,
NotificationManager.IMPORTANCE_HIGH
)
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.WHITE
notificationChannel.enableVibration(true)
notificationChannel.description = getString(R.string.swipe_description)
val notificationManager = requireActivity().getSystemService(
NotificationManager::class.java
)
notificationManager.createNotificationChannel(notificationChannel)
我很确定这是一个简单的原因,我只是没有看到它。任何想法都将受到欢迎。
【问题讨论】:
“它似乎不再起作用”,你能说得更具体一点吗?它会使您的应用程序崩溃吗?它不显示任何图像吗?图像是否以错误的顺序显示? 该应用程序确实运行并且它也显示图像。它只是不像我最初做的那样循环为轮播。只显示我请求的 X 张图片。 【参考方案1】:您使用空的Arraylist
初始化适配器并且适配器中的 Runnable 始终使用空列表 info
最好使用适配器内的项目列表作为单一事实来源:
viewModel.picInfo.observe(viewLifecycleOwner, Observer
// dont need to call notifyDatasetChanges() as diffutil will do the work
val newList = adapter.info.plus(it)
adapter.submitList(newList) adapter.info = newList
)
【讨论】:
我可能会误解您所解释的内容。我创建了一个 items 变量,它被分配为 MutableListinfo
(通过改变它的可见性)。我更正了答案。
好的。我仍然得到与我之前所说的相同的结果,并且轮播不是从一开始就开始,而是在中间的某个地方。以上是关于为啥 ViewPager 无限循环不起作用?的主要内容,如果未能解决你的问题,请参考以下文章