rt 现在更新到底部时,会出现闪动的情况,想请问大佬们有没有什么解决方案?成功了请喝咖啡
1
murmurkerman 42 天前
简单讲一下 RecyclerView 和 ItemView 结构,是某个 Item 会动态更新么,类似于 Ai 聊天应用么。
|
![]() |
2
lixyz OP @murmurkerman 就是一个类似于 AI 聊天的应用,item 是 TextView ,然后 SSE 流式更新这个 TextView
想要实现当 TextView 高于屏幕高度时,随着文本的增加,自行向下滚动 现在通过 scrollToPositionWithOffset 可以实现滚动到底部,但是随着流式更新 TextView ,会导致上下一跳一跳的 大佬有没有什么解决方案啊 |
![]() |
3
sankemao 42 天前
recyclerView 设置反向排列试过吗
|
4
murmurkerman 42 天前 via iPhone
用正序的 recycler view 比较合适。消息高度超过限制和不再自动滚动到底部。逆序的话要计算 scroll range 的变化,然后滚动变化的部分。
|
![]() |
5
lixyz OP @sankemao @murmurkerman 因为还有其他类型的卡片以及交互,所以没有尝试改变 rv 的渲染方向,实在不行我试一下吧,多谢二位
|
![]() |
6
qwwuyu 42 天前
试了一下,可以一直保持在底部,不会上下跳动,我这里没有去计算 TextView 改变后的高度,有需要可以自己监听控件高度变化,再去 scrollToPositionWithOffset.
代码图片 https://imgur.com/a/HU30yph ``` new Thread(() -> { while (!isFinishing() && run) { try { Thread.sleep(200); } catch (InterruptedException ignored) { } runOnUiThread(() -> { if (textTv != null) { textTv.setText(textTv.getText() + "asdasdasdasdasdasdasd"); int targetPosition = adapter.getItemCount() - 1; View targetView = linearLayoutManager.findViewByPosition(targetPosition); int offset = recyclerView.getHeight() - targetView.getHeight(); linearLayoutManager.scrollToPositionWithOffset(targetPosition, offset); } }); } }).start(); ``` |
7
murmurkerman 42 天前 ![]() 好久没写 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) } ) } } ``` |
![]() |
8
lixyz OP |
10
murmurkerman 41 天前 via iPhone
@lixyz item 有没有加 id 和 type
|