Android Jetpack:如何使用 PagingDataAdapter 在回收器视图中进行多项选择?

Leo*_*sch 1 paging android multi-select android-jetpack

我想在我的 Android 应用程序中进行多项选择。我以前做过,但只使用了 ArrayAdapter。

我有一个 Flow 作为我的数据集,并使用 PagingDataAdapter 和 ViewHolder。

我的问题是,如果数据集不仅仅是一个列表并且我无法真正轻松地访问它,如何进行多重选择。

如果您想查找代码,请查看以下内容:

片段 适配器 ViewHolder ViewModel

Leo*_*sch 5

我已经实现了一种自定义方法。

我在适配器中使用了可观察列表,并向视图持有者公开方法以选择它们自己。

您当然可以为此创建一个基类。我最终也应该这么做:)

我的代码:

适配器

class PhotoAdapter(
    private val context: Context,
    private val photoRepository: PhotoRepository,
    private val viewPhotoCallback: KFunction1<Int, Unit>,
    val lifecycleOwner: LifecycleOwner
) : PagingDataAdapter<Photo, PhotoItemViewHolder>(differCallback) {

    /**
     * Holds the layout positions of the selected items.
     */
    val selectedItems = ObservableArrayList<Int>()

    /**
     * Holds a Boolean indicating if multi selection is enabled. In a LiveData.
     */
    var isMultiSelectMode: MutableLiveData<Boolean> = MutableLiveData(false)

    override fun onBindViewHolder(holderItem: PhotoItemViewHolder, position: Int) {
        holderItem.bindTo(this, getItem(position))
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PhotoItemViewHolder =
        PhotoItemViewHolder(parent, context, photoRepository)

    /**
     * Called by ui. On Click.
     */
    fun viewPhoto(position: Int) {
        viewPhotoCallback.invoke(getItem(position)?.id!!)
    }

    /**
     * Disables multi selection.
     */
    fun disableSelection() {
        selectedItems.clear()
        isMultiSelectMode.postValue(false)
    }

    /**
     * Enables multi selection.
     */
    fun enableSelection() {
        isMultiSelectMode.postValue(true)
    }

    /**
     * Add an item it the selection.
     */
    fun addItemToSelection(position: Int): Boolean = selectedItems.add(position)

    /**
     * Remove an item to the selection.
     */
    fun removeItemFromSelection(position: Int) = selectedItems.remove(position)

    /**
     * Indicate if an item is already selected.
     */
    fun isItemSelected(position: Int) = selectedItems.contains(position)

    /**
     * Indicate if an item is the last selected.
     */
    fun isLastSelectedItem(position: Int) = isItemSelected(position) && selectedItems.size == 1

    /**
     * Select all items.
     */
    fun selectAll() {
        for (i in 0 until itemCount) {
            if (!isItemSelected(i)) {
                addItemToSelection(i)
            }
        }
    }

    /**
     * Get all items that are selected.
     */
    fun getAllSelected(): List<Photo> {
        val items = mutableListOf<Photo>()
        for(position in selectedItems) {
            val photo = getItem(position)
            if (photo != null) {
                items.add(photo)
            }
        }
        return items
    }

    companion object {
        private val differCallback = object : DiffUtil.ItemCallback<Photo>() {

            override fun areItemsTheSame(oldItem: Photo, newItem: Photo): Boolean =
                oldItem.id == newItem.id

            override fun areContentsTheSame(oldItem: Photo, newItem: Photo): Boolean =
                oldItem == newItem

        }
    }

}
Run Code Online (Sandbox Code Playgroud)

视图持有者

class PhotoAdapter(
    private val context: Context,
    private val photoRepository: PhotoRepository,
    private val viewPhotoCallback: KFunction1<Int, Unit>,
    val lifecycleOwner: LifecycleOwner
) : PagingDataAdapter<Photo, PhotoItemViewHolder>(differCallback) {

    /**
     * Holds the layout positions of the selected items.
     */
    val selectedItems = ObservableArrayList<Int>()

    /**
     * Holds a Boolean indicating if multi selection is enabled. In a LiveData.
     */
    var isMultiSelectMode: MutableLiveData<Boolean> = MutableLiveData(false)

    override fun onBindViewHolder(holderItem: PhotoItemViewHolder, position: Int) {
        holderItem.bindTo(this, getItem(position))
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PhotoItemViewHolder =
        PhotoItemViewHolder(parent, context, photoRepository)

    /**
     * Called by ui. On Click.
     */
    fun viewPhoto(position: Int) {
        viewPhotoCallback.invoke(getItem(position)?.id!!)
    }

    /**
     * Disables multi selection.
     */
    fun disableSelection() {
        selectedItems.clear()
        isMultiSelectMode.postValue(false)
    }

    /**
     * Enables multi selection.
     */
    fun enableSelection() {
        isMultiSelectMode.postValue(true)
    }

    /**
     * Add an item it the selection.
     */
    fun addItemToSelection(position: Int): Boolean = selectedItems.add(position)

    /**
     * Remove an item to the selection.
     */
    fun removeItemFromSelection(position: Int) = selectedItems.remove(position)

    /**
     * Indicate if an item is already selected.
     */
    fun isItemSelected(position: Int) = selectedItems.contains(position)

    /**
     * Indicate if an item is the last selected.
     */
    fun isLastSelectedItem(position: Int) = isItemSelected(position) && selectedItems.size == 1

    /**
     * Select all items.
     */
    fun selectAll() {
        for (i in 0 until itemCount) {
            if (!isItemSelected(i)) {
                addItemToSelection(i)
            }
        }
    }

    /**
     * Get all items that are selected.
     */
    fun getAllSelected(): List<Photo> {
        val items = mutableListOf<Photo>()
        for(position in selectedItems) {
            val photo = getItem(position)
            if (photo != null) {
                items.add(photo)
            }
        }
        return items
    }

    companion object {
        private val differCallback = object : DiffUtil.ItemCallback<Photo>() {

            override fun areItemsTheSame(oldItem: Photo, newItem: Photo): Boolean =
                oldItem.id == newItem.id

            override fun areContentsTheSame(oldItem: Photo, newItem: Photo): Boolean =
                oldItem == newItem

        }
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 是的,我发现了一些实现这个问题的问题,但是你的存储库帮助了我。感谢如此干净的代码。 (2认同)