简体   繁体   English

删除 Android ViewPager2 中的项目

[英]Delete Item in Android ViewPager2

I am updating my code from using androidx.viewpager to androidx.viewpager2 .我正在将我的代码从使用androidx.viewpager更新为androidx.viewpager2 I am paging through an undetermined number of fragments showing data records retrieved from a database.我正在翻阅数量不确定的片段,这些片段显示从数据库中检索到的数据记录。 Loading the view pager and paging through my data works nicely but I'm having some trouble with deleting an item and updating the pager adapter.加载视图寻呼机并通过我的数据进行分页效果很好,但我在删除项目和更新寻呼机适配器时遇到了一些麻烦。 I want to delete an item at any given position by calling the removeItem() method (see code below) on my adapter.我想通过在我的适配器上调用removeItem()方法(参见下面的代码)来删除任何给定 position 的项目。 That should remove the item from my database as well as my fragment and then update the view.那应该从我的数据库以及我的片段中删除该项目,然后更新视图。

Result is that the correct item is removed from the database.结果是从数据库中删除了正确的项目。 But it does not remove the intended fragment from my view pager but the next page instead.但它不会从我的视图寻呼机中删除预期的片段,而是从下一页中删除。 The current page remains visible.当前页面仍然可见。 I have a bit offsetting the position by plus or minus 1 with no success - in contrary: in those cases my delete routine performed as initially expected.我将 position 偏移了正负 1 但没有成功 - 相反:在这些情况下,我的删除例程按最初预期执行。 I also tried similar considerations as given eg here .我也尝试过类似的考虑,例如这里给出的。

I'd like to achieve the following behavior:我想实现以下行为:

  1. When deleting any item, the page should be removed and the next one in the list displayed.删除任何项目时,应删除该页面并显示列表中的下一个项目。
  2. When deleting the last/rightmost item in the list, the page should be removed and the previous (now last) page shown.当删除列表中的最后一个/最右边的项目时,应该删除该页面并显示前一个(现在是最后一个)页面。
  3. When deleting the last remaining item (none left) the activity should finish.当删除最后一个剩余项目(一个都没有)时,活动应该完成。

My adapter code:我的适配器代码:

internal class ShapePagerAdapter(private val activity: AppCompatActivity) : FragmentStateAdapter(activity) {
    private val dbManager: DatabaseManager
    private var shapeIds: MutableList<String>? = null

    init {
        dbManager = DatabaseManager(activity)
        try {
            shapeIds = dbManager.getShapeIds()
        } catch (e: DatabaseAccessException) {
            // ...
        }
    }

    override fun getItemCount(): Int {
        return if (null != shapeIds) shapeIds!!.size else 0
    }

    override fun createFragment(position: Int): Fragment {
        return ShapeFragment.newInstance(shapeIds!![position])
    }

    fun removeItem(activity: AppCompatActivity, position: Int) {
        try {
            // Remove from Database.
            dbManager.deleteShape(shapeIds!![position])
            // Remove from View Pager.
            shapeIds!!.removeAt(position)
            notifyItemRemoved(position)
            notifyItemRangeChanged(position , itemCount)
            // Close if nothing to show anymore.
            if (itemCount == 0) {
                activity.finish()
            }
        } catch (e: DatabaseAccessException) {
            // ...
        }
    }
}

Closer study of FragmentStateAdapter reveals that two of its methods must be overridden in this case:FragmentStateAdapter的进一步研究表明,在这种情况下必须重写它的两个方法:

containsItem(long itemId) and getItemId(int position) containsItem(long itemId)getItemId(int position)

Default implementation works for collections that don't add, move, remove items.默认实现适用于不添加、移动、删除项目的 collections。

Searching for that I found an answer to a similar question , pointing me in the right direction.通过搜索,我找到了类似问题的答案,为我指明了正确的方向。 It does not produce the exact behavior given in my question, which is why I'm posting a slightly adapted version.它不会产生我的问题中给出的确切行为,这就是为什么我要发布一个稍微改编的版本。

Key is that those two methods are implemented in cases there can be changes to the sequence of items.关键是这两种方法是在项目序列可能发生变化的情况下实施的。 To enable this I maintain a map of items and item ids and update when there are changes to the sequence, in this case a removed item.为了实现这一点,我维护了一个 map 的项目和项目 ID,并在序列发生变化时进行更新,在本例中是删除的项目。

internal class ShapePagerAdapter(private val activity: AppCompatActivity) : FragmentStateAdapter(activity) {
    private val dbManager: DatabaseManager
    private lateinit var shapeIds: MutableList<String>
    private lateinit var itemIds: List<Long>

    init {
        dbManager = DatabaseManager(activity)
        try {
            shapeIds = dbManager.getShapeIds()
            updateItemIds()
        } catch (e: DatabaseAccessException) {
            // ...
        }
    }

    override fun getItemCount(): Int = shapeIds.size

    override fun createFragment(position: Int): Fragment = ShapeFragment.newInstance(shapeIds[position])

    fun removeItem(activity: AppCompatActivity, position: Int) {
        try {
            dbManager.deleteShape(shapeIds[position])
            shapeIds.removeAt(position)
            notifyItemRemoved(position)
            notifyItemRangeChanged(position , itemCount)
            updateItemIds()
            if (itemCount == 0) activity.finish()
        } catch (e: DatabaseAccessException) {
            // ...
        }
    }

    private fun updateItemIds() {
        itemIds = shapeIds.map { it.hashCode().toLong() }
    }

    override fun getItemId(position: Int): Long = shapeIds[position].hashCode().toLong()

    override fun containsItem(itemId: Long): Boolean = itemIds.contains(itemId)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM