我们的 App 中有这个功能,我们可以在其中上下拖动回收站视图项目。
在 ItemTouchHelper.Callback() 的 onMove() 中,我们调用
adapter.onItemMove(source.adapterPosition, target.adapterPosition)
适配器代码是这样的
override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean {
Collections.swap(dataList, fromPosition, toPosition)
notifyItemMoved(fromPosition, toPosition)
return true
}
现在,早期的适配器类正在扩展 RecyclerView.Adapter() 并且我们有以下方法来使用 DiffUtils 更新我们的列表
fun setDataList(feeds: List<User>): DiffUtil.DiffResult {
val diffResult = DiffUtil.calculateDiff(ContentDiffCall(mFeeds, feeds))
this.mFeeds.clear()
this.mFeeds.addAll(feeds)
return diffResult
}
拖放工作正常。
但是当我们从 ListAdapter 扩展我们的适配器类时,已经工作的功能(拖放)被破坏了。回收站视图中的第一个项目没有拖动到第二个项目之外,并且拖动的位置项目也没有得到更新。
恢复 ListAdapter 实现使其再次工作。
无法理解为什么当 ListAdapter 本身扩展 RecyclerView.Adapter 时这不起作用。
适配器类
class ContentListAdapter(
private val headerListener: HeaderClickListener?,
private val listener: ListItemClickListener?,
private val screen: Screen,
private val feedInteractor: FeedInteractionManager
) : ListAdapter<BaseUiModel, RecyclerView.ViewHolder>(ContentListDiffCall()), ContentTouchHelperAdapter {
private var dataList = ArrayList<BaseUiModel>()
init {
setHasStableIds(true)
}
fun setDataList(data: List<BaseUiModel>) {
dataList.clear()
dataList.addAll(data)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
HFType.CONTENT_LIST_HEADER.ordinal -> ContentListHeaderViewHolder.getInstance(
parent,
headerListener,
R.layout.layout_content_list_header,
screen
)
HFType.SONG.ordinal -> SongViewHolder.getInstance(parent, listener)
else -> throw RuntimeException("there is no type that matches the type $viewType ; make sure your using types correctly")
}
}
override fun getItemViewType(position: Int): Int {
return getItem(position).hfType.ordinal
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val data = getItem(position)
when (holder) {
is SongViewHolder -> {
if (data is SongUiModel) {
holder.bindViews(data)
}
}
is ContentListHeaderViewHolder -> {
if (data is HeaderUiModel) {
holder.bindViews(data)
}
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: MutableList<Any>) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position)
return
}
val data = getItem(position)
when (holder) {
is SongViewHolder -> {
if (data is SongUiModel) {
holder.bindViews(data, payloads)
}
}
is ContentListHeaderViewHolder -> {
if (data is HeaderUiModel) {
holder.bindViews(data, payloads)
}
}
}
}
override fun getItemId(position: Int): Long {
val data = getItem(position)
return data.hashCode().toLong()
}
override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean {
Collections.swap(dataList, fromPosition, toPosition)
notifyItemMoved(fromPosition, toPosition)
return true
}
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
super.onViewAttachedToWindow(holder)
if (holder is HomeFeedViewHolder<*>) {
holder.onHolderAttachedInViewPort()
}
}
}
interface ContentTouchHelperAdapter {
fun onItemMove(fromPosition: Int, toPosition: Int): Boolean
}
片段内的代码片段
private fun setUpRecyclerView() {
rv_item_list.apply {
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
recycledViewPool.setMaxRecycledViews(HFType.SONG.ordinal, 12)
recycledViewPool.setMaxRecycledViews(HFType.CONTENT_LIST_HEADER.ordinal, 1)
}
val spaceItemDecorator = ContentListSpaceDecorator(25.dpToPx())
rv_item_list.addItemDecoration(spaceItemDecorator)
adapter = ContentListAdapter(this, this, this, screen, this)
rv_item_list.adapter = adapter
val callback = SimpleTouchListener(adapter, contentListViewModel)
itemTouchHelper = ItemTouchHelper(callback)
itemTouchHelper.attachToRecyclerView(rv_item_list)
}
SimpleTouchListener 类
class SimpleTouchListener(
private val listAdapter: ContentListAdapter,
private val viewModel: ContentListViewModel
) :
ItemTouchHelper.Callback() {
private var fromPosition: Int? = null
private var toPosition: Int? = null
override fun isLongPressDragEnabled(): Boolean {
return false
}
override fun isItemViewSwipeEnabled(): Boolean {
return false
}
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
var dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
if (viewHolder is ContentListHeaderViewHolder) {
dragFlags = 0
}
return makeMovementFlags(dragFlags, 0)
}
override fun onMove(
recyclerView: RecyclerView,
source: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
if (source.itemViewType != target.itemViewType) {
return false
}
if (fromPosition == null) {
fromPosition = source.adapterPosition
}
toPosition = target.adapterPosition
listAdapter.onItemMove(source.adapterPosition, target.adapterPosition)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, i: Int) {
// Notify the adapter of the dismissal
}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
if (viewHolder is ItemTouchHelperViewHolder) {
val itemViewHolder = viewHolder as ItemTouchHelperViewHolder?
itemViewHolder?.onItemSelected()
}
}
super.onSelectedChanged(viewHolder, actionState)
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
if (viewHolder is ItemTouchHelperViewHolder) {
// Tell the view holder it's time to restore the idle state
val itemViewHolder = viewHolder as ItemTouchHelperViewHolder
itemViewHolder.onItemClear()
}
if (fromPosition != null && toPosition != null) {
//This method updates the list ordering in DB
viewModel.onContentPositionChange(fromPosition, toPosition)
}
fromPosition = null
toPosition = null
}
}
我们在成功时从观察者那里调用 setAdapterMethod
private fun setAdapterData(contentList: List<BaseUiModel>?) {
contentList?.let { it ->
adapter.setDataList(it)
adapter.submitList(it)
}
}