У нас есть эта функция в нашем приложении, где мы можем перетаскивать элементы просмотра переработчика вверх и вниз.
Внутри onMove () ItemTouchHelper.Callback () мы вызываем
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 из наблюдателя на Success
private fun setAdapterData(contentList: List<BaseUiModel>?) {
contentList?.let { it ->
adapter.setDataList(it)
adapter.submitList(it)
}
}