如何解决当 RecyclerView 连续获得 2 个相同的对象时,它将“相机”移至第二个,将前一个留在视图之外,即“上方”
在片段中:
@AndroidEntryPoint
class DrillerFragment : Fragment(R.layout.cardstack_layout),CardStackListener {
private val viewModel: DrillerViewModel by viewModels()
private lateinit var currentWord :Word
private val drillerAdapter = DrillerAdapter()
override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
val binding = CardstackLayoutBinding.bind(view)
viewModel.getLivedataList().observe(viewLifecycleOwner) {
drillerAdapter.submitList(it)
Log.d(TAG,"drlr workWorkList.size = " + it.size)
}
val drillerLayoutManager = CardStackLayoutManager(requireContext(),this)
binding.apply {
cardStackView.apply {
layoutManager = drillerLayoutManager
adapter = drillerAdapter
itemAnimator = null // ХЗ НАДО ЛИ
}
}
viewModel.get4words()
}
override fun onCardSwiped(direction: Direction?) {
if (direction == Direction.Bottom) {
currentWord.shown = false
viewModel.update(currentWord)
}
viewModel.removeAndAddWord(currentWord)
Log.d(TAG,currentWord.foreign + " is removed. (drlr)")
}
override fun onCardAppeared(view: View?,position: Int) {
currentWord = drillerAdapter.getWordAt(position)
Log.d(TAG,"onCardAppeared: " + currentWord.foreign + " IS NOW currentWord,position in adapter - " + position + " (drlr)")
}
override fun onCardDisappeared(view: View?,"onCardDisappeared: " + currentWord.foreign + " IS NOW currentWord,position in adapter - " + position + " (drlr)")
}
视图模型代码:
class DrillerViewModel @ViewModelInject constructor(
private val wordDao: WordDao,) : ViewModel() {
var mList = ArrayList<Word>()
val mLivedataList = MutableLiveData<List<Word>>()
val m4words = wordDao.get4wordsRx()
val m1word = wordDao.get1wordRx()
val composite = CompositeDisposable()
fun getLivedataList(): LiveData<List<Word>> {
return mLivedataList
}
fun get4words() {
m4words.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object :
SingleObserver<List<Word>> {
override fun onSubscribe(d: Disposable) {
composite.add(d)
}
override fun onSuccess(t: List<Word>) {
mList.addAll(t)
mLivedataList.value = mList
}
override fun onError(e: Throwable) {
// empty
}
})
}
fun removeAndAddWord(word: Word) {
mList = ArrayList<Word>(mList)
mList.remove(word)
Log.d(TAG,"(drlr) removeAndAddWord: mList.size = " + mList.size)
m1word.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Word> {
override fun onSubscribe(d: Disposable) {
composite.add(d)
}
override fun onSuccess(t: Word) {
mList.add(t)
mLivedataList.value = mList
Log.d(TAG,"(drlr) removeAndAddWord called,now mList contains: ")
mList.forEach { item -> Log.d(TAG,"(drlr) " + item.foreign) }
}
override fun onError(e: Throwable) {
// empty
}
})
}
fun update(word: Word) = viewModelScope.launch {
wordDao.update(word)
}
}
(CardStackView本身必须总是包含4个单词,它是从数据库中随机获取的,有时可以获取相同的单词也没关系。这是一个学习单词的应用程序。)
我注意到的:
- 当一行中有 2 个具有相似值的项时,然后在 removeAndAdd() 方法上,以一种奇怪的方式将位于位置 0 的项保留在 recycleView 列表中,并且回收视图移动到位置 1,上面留下零项,超出视野范围。
- 当正好有 2 个连续的单词完全相同时,就会发生这种情况。视图,当顶部位置被其中一个占据,第二个在它的正下方时,立即移动到第二个,第一个在视图之外保持“更高”(但仍然在列表中,好像被适配器中的帐户,因为如果这个“堵塞”消失(即下一个 Word 完全不同),那么视图将返回到第一个丢失的项目。
- 基数中的单词越少,适配器位置从 0 到 1 移动的频率就越高。如果向下滑动(见 onSwipe()),则 Word.shown 被设置为 false,并且这个单词不会再次出现(get1word 方法只从 base 中取带有 shown = true 的单词)),然后更少的单词包括,工作列表中的重复次数越多,这样的“卡纸”就越多。 CardStackView 到达底部,屏幕变为空白,尽管列表中有未删除的单词。
我无法理解如何治愈它。感谢您的帮助。
这是适配器代码:
class DrillerAdapter() : ListAdapter<Word,DrillerAdapter.DrillerViewHolder>(DrillerDiff()) {
inner class DrillerViewHolder(private val binding: CardstackItemBinding) :
RecyclerView.ViewHolder(
binding.root
) {
init {
binding.apply {
root.setOnClickListener {
val position = adapterPosition
if (position != CardStackView.NO_POSITION) {
tvNativ.visibility = View.VISIBLE
}
}
}
}
fun bind(word: Word) {
binding.apply {
tvForeign.text = word.foreign
tvNativ.text = word.nativ
tvNativ.visibility = View.INVISIBLE
}
}
}
override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): DrillerViewHolder {
val binding = CardstackItemBinding.inflate(
LayoutInflater.from(parent.context),parent,false
)
return DrillerViewHolder(binding)
}
override fun onBindViewHolder(holder: DrillerViewHolder,position: Int) {
val currentItem = getItem(position)
holder.bind(currentItem)
}
fun getWordAt(position: Int): Word {
return getItem(position)
}
class DrillerDiff : DiffUtil.ItemCallback<Word>() {
override fun areItemsTheSame(oldItem: Word,newItem: Word) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Word,newItem: Word) =
oldItem == newItem
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。