在 ConstraintLayout 中选择 Spinner 项目时,滚动视图跳到顶部
Posted
技术标签:
【中文标题】在 ConstraintLayout 中选择 Spinner 项目时,滚动视图跳到顶部【英文标题】:Scrollview jumps to top when selecting Spinner item in ConstraintLayout 【发布时间】:2020-07-06 12:54:35 【问题描述】:我有一个 ScrollView
,其中包含一个 ConstraintLayout
,还有许多 Spinners
及其标签。
每当我在任何微调器中选择一个项目时,滚动视图都会滚动到顶部,并且用户必须在每次选择后滚动回他们所在的位置。
我试过了:
添加android:descendantFocusability="beforeDescendants"
android:focusable="true"
到滚动视图。
将android:descendantFocusability="blocksDescendants"
添加到约束布局。
android:focusable="false" android:focusableInTouchMode="false"
添加到每个视图。
在约束布局的顶部添加一个带有<requestFocus/>
的空项
但是无论我做什么,滚动视图都会在我选择一个微调项后跳到顶部。
这是我的 xml 布局:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_>
<androidx.constraintlayout.widget.ConstraintLayout
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_
android:layout_>
<TextView
android:id="@+id/label2"
android:layout_
android:layout_
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Test"
app:layout_constraintEnd_toStartOf="@+id/spinner2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/spinner1" />
<TextView
android:id="@+id/label5"
android:layout_
android:layout_
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Test"
app:layout_constraintEnd_toStartOf="@+id/spinner5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/label4" />
<TextView
android:id="@+id/label6"
android:layout_
android:layout_
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Test"
app:layout_constraintEnd_toStartOf="@+id/spinner6"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/spinner5" />
<TextView
android:id="@+id/label8"
android:layout_
android:layout_
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Test"
app:layout_constraintEnd_toStartOf="@+id/spinner8"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/label7" />
<TextView
android:id="@+id/label4"
android:layout_
android:layout_
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Test"
app:layout_constraintEnd_toStartOf="@+id/spinner4"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/spinner3" />
<TextView
android:id="@+id/label7"
android:layout_
android:layout_
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Test"
app:layout_constraintEnd_toStartOf="@+id/spinner7"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/label6" />
<Spinner
android:id="@+id/spinner1"
android:layout_
android:layout_
android:layout_marginEnd="16dp"
android:entries="@array/yes_or_no"
app:layout_constraintBottom_toBottomOf="@+id/label1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/label1" />
<Spinner
android:id="@+id/spinner2"
android:layout_
android:layout_
android:layout_marginEnd="16dp"
android:entries="@array/yes_or_no"
app:layout_constraintBottom_toBottomOf="@+id/label2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/label2" />
<Spinner
android:id="@+id/spinner3"
android:layout_
android:layout_
android:layout_marginEnd="16dp"
android:entries="@array/yes_or_no"
app:layout_constraintBottom_toBottomOf="@+id/label3"
app:layout_constraintEnd_toEndOf="parent" />
<Spinner
android:id="@+id/spinner5"
android:layout_
android:layout_
android:layout_marginEnd="16dp"
android:entries="@array/yes_or_no"
app:layout_constraintBottom_toBottomOf="@+id/label5"
app:layout_constraintEnd_toEndOf="parent" />
<Spinner
android:id="@+id/spinner6"
android:layout_
android:layout_
android:layout_marginEnd="16dp"
android:entries="@array/yes_or_no"
app:layout_constraintBottom_toBottomOf="@+id/label6"
app:layout_constraintEnd_toEndOf="parent" />
<Spinner
android:id="@+id/spinner7"
android:layout_
android:layout_
android:layout_marginEnd="16dp"
android:entries="@array/yes_or_no"
app:layout_constraintBottom_toBottomOf="@+id/label7"
app:layout_constraintEnd_toEndOf="parent" />
<Spinner
android:id="@+id/spinner9"
android:layout_
android:layout_
android:layout_marginEnd="16dp"
android:layout_marginBottom="1dp"
android:entries="@array/yes_or_no"
app:layout_constraintBottom_toBottomOf="@+id/label9"
app:layout_constraintEnd_toEndOf="parent" />
<Spinner
android:id="@+id/spinner8"
android:layout_
android:layout_
android:layout_marginEnd="16dp"
android:entries="@array/yes_or_no"
app:layout_constraintBottom_toBottomOf="@+id/label8"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/label8" />
<TextView
android:id="@+id/label9"
android:layout_
android:layout_
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Test"
app:layout_constraintEnd_toStartOf="@+id/spinner9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/label8" />
<Spinner
android:id="@+id/spinner4"
android:layout_
android:layout_
android:layout_marginEnd="16dp"
android:entries="@array/yes_or_no"
app:layout_constraintBottom_toBottomOf="@+id/label4"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/label3"
android:layout_
android:layout_
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Test"
app:layout_constraintEnd_toStartOf="@+id/spinner3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/spinner2" />
<TextView
android:id="@+id/label1"
android:layout_
android:layout_
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="8dp"
android:text="Test"
app:layout_constraintEnd_toStartOf="@+id/spinner1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
和数组
<string-array name="yes_or_no">
<item></item>
<item>Yes</item>
<item>No</item>
</string-array>```
Thank you
【问题讨论】:
您的 xml 有错误,我们没有您的数组 嗨 Mohammad,我已经修复了布局并添加了数组代码。谢谢。 嗨,谢谢埃里克 【参考方案1】:创建一个 ScrollBehaviour 类
public class ScrollBehaviour
private final String mCategory;
private final RecyclerView mRv;
private final RecyclerView.LayoutManager mLayoutManager;
public ScrollBehaviour(String category,
RecyclerView rv,
RecyclerView.LayoutManager layoutManager)
this.mCategory = category;
this.mRv = rv;
this.mLayoutManager = layoutManager;
/**
* Scroll's target @link RecyclerView to top if current pos is zero and user is not
* scrolling or this was an auto update. By definition auto update can never happen
* when user has just returned from details activity.
*
* @param forceTop Flag to tell if auto update just happened.
*/
public void applyAutoScrollBehaviour(boolean forceTop)
boolean isAtTop = isAtTop();
if (forceTop ||
(isAtTop && mRv.getScrollState() != RecyclerView.SCROLL_STATE_DRAGGING))
Timber.v(mCategory + " => applyAutoScrollBehaviour. "
+ " AutoUpdate: " + forceTop
+ " IsAtTop: " + isAtTop);
scrollToTop();
/**
* Scroll's target @link RecyclerView to top.
*/
public void scrollToTop()
mRv.scrollToPosition(0);
private boolean isAtTop()
if(mLayoutManager instanceof LinearLayoutManager)
return ((LinearLayoutManager)mLayoutManager).findFirstCompletelyVisibleItemPosition() == 0;
else
//TODO: Handler staggered grid layout manager
return false;
在你的 Activity/Fragment 中
ScrollBehaviour scrollBehaviour = ScrollBehaviour(
"String",
"your_recyclerview,
"recyclerview_layoutManger");
在需要的地方调用 scrollToTop() 方法
scrollBehaviour.scrollToTop()
【讨论】:
以上是关于在 ConstraintLayout 中选择 Spinner 项目时,滚动视图跳到顶部的主要内容,如果未能解决你的问题,请参考以下文章
是否建议在 Android 的 ConstraintLayout 中使用 LinearLayout?
ConstraintLayout中Chains和Guideline的使用
ConstraintLayout 中的 ListView 在预览中展开为全屏