好久没写 android view 哈哈哈,我写出来了,花掉了所有的摸鱼时间,
https://github.com/Murmurl912/android_recycler_view_chat.git 。
总结下:
1. 去掉 RecyclerView 的 ItemAnimator
2. 在更新 Item 的时候,判断是否在底部,已经是底部的时候滚动到底部。
3. 我之前的方案是会加一个 FirstItem 和 LastItem 的占位 Item 到 RecyclerView 中,方便实现滚动到底部和顶部。
Core Code:
```kotlin
class MainActivity : ComponentActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
private val adapter by lazy {
ItemAdapter()
}
private var id = 1L
private val items = LinkedHashMap<Long, Item>()
private var job: Job? = null
private val layoutManager by lazy {
binding.recyclerView.layoutManager as LinearLayoutManager
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(binding.root)
binding.root.fitsSystemWindows = true
binding.recyclerView.adapter = adapter
binding.recyclerView.itemAnimator = null
binding.generate.setOnClickListener {
if (job?.isActive == true) {
return@setOnClickListener
}
var item = Item.MessageItem(id++, "")
items[
item.id] = item
updateItems()
job = lifecycleScope.launch {
MessageApi.generate()
.collect { text ->
item = item.copy(text = item.text + text, isGenerating = true).also {
items[
it.id] = it
updateItems()
}
// scroll to bottom here
val isAtBottom =
layoutManager.findLastCompletelyVisibleItemPosition() == adapter.itemCount - 1
if (isAtBottom) {
layoutManager.scrollToPosition(adapter.itemCount - 1)
}
}
item = item.copy(isGenerating = false).also {
items[
it.id] = it
updateItems()
}
}
}
}
private fun updateItems() {
adapter.updateItems(items.values.toMutableList()
.apply {
add(0, Item.FirstItem)
add(Item.LastItem)
}
)
}
}
```