当RecyclerView
是ConstraintLayout
的子代时,我遇到了问题。最初,RecyclerView
位于Relative-
,Frame-
和LinearLeayout
的视图层次结构的深处,并且一切正常,直到我决定使用ConstraintLayout展平视图树。我注意到,每次由于任何原因(窗口大小调整,数据集更改通知等)引起布局更改时,RecyclerView
的滚动位置都会更改。
例如,每次我显示和隐藏软键盘时,内容回收器视图都会偏移一定数量的像素。
我能够在非常简单的布局上重现此行为:
ConstraintLayout
|---RecyclerView
|---Button
|---EditText
如果我设置约束以使RecyclerView
放置在ConstraintLayout
的任何其他子元素上在上方(这意味着RecyclerView具有底部约束),并且如果我使用{{1} }和LinearLayoutManager
一起,可以重现上述行为。
我该如何解决(我不想改变滚动位置)?也许RecyclerView和/或ConstraintLayout上有一些我不知道的标志...
这是我的reverseLayout = true
:
layout.xml
这是在<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintTop_toTopOf="parent"
/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Notify Items Changed"
app:layout_constraintBottom_toTopOf="@+id/edit_text"
app:layout_constraintEnd_toStartOf="parent"
app:layout_constraintStart_toEndOf="parent"
/>
<EditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
/>
</android.support.constraint.ConstraintLayout>
中设置RecyclerView
的代码:
Activity.onCreate()
这是调试日志的一部分,这些调试日志是在单击按钮几次后收集的:
setContentView(R.layout.activity_main)
val adapter = Adapter()
val layoutManager = LinearLayoutManager(this)
layoutManager.orientation = LinearLayoutManager.VERTICAL
layoutManager.reverseLayout = true
val recycler = findViewById<RecyclerView>(R.id.recycler)
recycler.layoutManager = layoutManager
recycler.adapter = adapter
recycler.addOnLayoutChangeListener { _, _, _, _, bottom, _, _, _, oldBottom ->
Log.d("TEST", "bottom=$bottom, oldBottom=$oldBottom")
}
recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
Log.d("TEST", "Scrolled: dx=$dx, dy=$dy")
Log.d("TEST", "offset = " + recycler.computeVerticalScrollOffset())
}
})
findViewById<Button>(R.id.button)
.setOnClickListener {
adapter.notifyDataSetChanged()
}
滚动位置正在缓慢变化,内容正在向上滚动。这种变化大致等于D/TEST: Scrolled: dx=0, dy=0
D/TEST: offset = 4167
D/TEST: bottom=1253, oldBottom=1253
D/TEST: Scrolled: dx=0, dy=0
D/TEST: offset = 3887
D/TEST: bottom=1253, oldBottom=1253
D/TEST: Scrolled: dx=0, dy=0
D/TEST: offset = 3607
D/TEST: bottom=1253, oldBottom=1253
D/TEST: Scrolled: dx=0, dy=0
D/TEST: offset = 3327
D/TEST: bottom=1253, oldBottom=1253
以下的小部件的总高度。
仅当满足所有条件时,我才能重现此行为:
RecyclerView
位于RecyclerView
内ConstraintLayout
下还有其他同级小工具RecyclerView
与标志LinearLayoutManager
或reverseLayout
中的任何一个设置为stackFromBottom
一起使用。我使用的true
版本是ConstraintLayout
。