android - 在 ConstraintLayout 中选择 Spinner 项目时,滚动视图跳到顶部
问题描述
我有一个ScrollView
包含一个ConstraintLayout
,有许多Spinners
及其标签的。
每当我在任何微调器中选择一个项目时,滚动视图都会滚动到顶部,并且用户必须在每次选择后滚动回他们所在的位置。
我努力了:
添加
android:descendantFocusability="beforeDescendants" android:focusable="true"
到滚动视图。添加
android:descendantFocusability="blocksDescendants"
到约束布局。- 添加
android:focusable="false" android:focusableInTouchMode="false"
到每个视图。 <requestFocus/>
在constraintLayout 的顶部添加一个空项目
但无论我做什么,在我选择一个微调项后,滚动视图都会跳到顶部。
这是我的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_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/label2"
android:layout_width="0dp"
android:layout_height="wrap_content"
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_width="0dp"
android:layout_height="wrap_content"
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_width="0dp"
android:layout_height="wrap_content"
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_width="0dp"
android:layout_height="wrap_content"
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_width="0dp"
android:layout_height="wrap_content"
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_width="0dp"
android:layout_height="wrap_content"
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_width="150dp"
android:layout_height="wrap_content"
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_width="150dp"
android:layout_height="wrap_content"
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_width="150dp"
android:layout_height="wrap_content"
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_width="150dp"
android:layout_height="wrap_content"
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_width="150dp"
android:layout_height="wrap_content"
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_width="150dp"
android:layout_height="wrap_content"
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_width="150dp"
android:layout_height="wrap_content"
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_width="150dp"
android:layout_height="wrap_content"
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_width="0dp"
android:layout_height="wrap_content"
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_width="150dp"
android:layout_height="wrap_content"
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_width="0dp"
android:layout_height="wrap_content"
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_width="0dp"
android:layout_height="wrap_content"
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
解决方案
创建一个 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;
}
}
}
在您的活动/片段中
ScrollBehaviour scrollBehaviour = ScrollBehaviour(
"String",
"your_recyclerview,
"recyclerview_layoutManger");
在需要的地方调用 scrollToTop() 方法
scrollBehaviour.scrollToTop()
推荐阅读
- xsl-fo - XSL-FO 单页布局
- r - 考试的解决方案 pdf 第一页是否可编辑?
- python - 为什么 Python 终端说我的 .dat 文件不存在?
- arrays - mongodb 不推送另一个对象,而是替换原始对象数据
- javascript - 在客户端浏览器中启动 Puppeteer 浏览器
- xamarin.forms - Xamarin.Forms - 如何检查我的应用程序是否使用广告标识符 (IDFA)?
- r - Rmarkdown中图表和表格的并排显示
- javascript - node-soap - TypeError:回调不是函数
- python - 使用 Python 在 numpy boolen 之间转换为两种状态的有效方法
- android - 从 macOS 应用程序运行的脚本中的 adb 屏幕截图