如何从 ScrollView 内的 RecyclerView 中移除焦点?

Posted

技术标签:

【中文标题】如何从 ScrollView 内的 RecyclerView 中移除焦点?【英文标题】:How to remove focus from RecyclerView inside ScrollView? 【发布时间】:2016-10-17 11:03:33 【问题描述】:

我有一个包含 ImageView 和 RecyclerView 的 Scrollview。 如果导航抽屉打开然后关闭 RecyclerView 自动滚动到顶部,如何停止?

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
xmlns:app="http://schemas.android.com/apk/res-auto">

<ScrollView
    android:layout_
    android:layout_
    android:id="@+id/scrollViewMain"
    >

    <LinearLayout
        android:layout_
        android:layout_
        android:orientation="vertical">

       <ImageView
           android:layout_
           android:layout_
           android:id="@+id/imageView_main_icons_line"
           android:src="@drawable/main_line" />

              ...


       <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView_activity_main_passenger_log"
            android:paddingBottom="2dp"
            android:layout_
            android:layout_ />

    </LinearLayout>
</ScrollView>
</RelativeLayout>

【问题讨论】:

将 RecyclerView 放入 ScrollView 根本不是一个好主意。通过使用这种结构,您可以很容易地遇到点击/滑动事件的麻烦。我的建议 - 改变你的设计 @TodorKostov 我不能,除了这个问题一切都很好,recyclerView 的高度是 wrap_content 所以可以把 recyclerview 放在滚动视图中 【参考方案1】:

这个问题是因为recyclerView有默认焦点。

解决方案

<LinearLayout
    android:layout_
    android:layout_
    android:descendantFocusability="blocksDescendants"
    android:orientation="vertical">

android:descendantFocusability="blocksDescendants" 添加到您的滚动视图的直接布局中

【讨论】:

将 android:descendantFocusability="blocksDescendants" 添加到 RecyclerView 的父级,即 LinearLayout,并且有效。 请务必在下方查看landerlyoung 的回答。遵循这个公认的答案可能会给使用物理键盘的用户带来许多问题。默认情况下,每个 Android 应用都可以使用硬键盘,除非您盲目地遵循 Rahul Devanavar 的回答。 没有帮助。我在 recyclerview 周围有相对布局。 当您在视图持有者处使用处理程序执行任何操作以定期更新内容时非常有用。谢谢@Rahul【参考方案2】:

那是因为 RecyclerView 总是设置:

setFocusableInTouchMode(true);

这是在其构造函数中硬编码的。

所以如果你在你的 XML 中为 RecyclerView 应用这些属性

android:focusable="false"
android:focudeableInTouchMode="false"

那没用,你最终会得到 recycleView.isFocusable() == true...

所以最优雅的解决方案是为 RecyclerView 的 Parent 禁用 foucusable。

<LinearLayout
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:descendantFocusability="blocksDescendants"
    ...
    >
    <android.support.v7.widget.RecyclerView
        ...
    />
/>

或者你可以简单地 setFocusable(false)

【讨论】:

它可以工作,但它最终会阻止 scrollview/nestedscrollview 内的任何孩子【参考方案3】:

从这里查看 clearFocus() Android Dev Doc.

您可以将 DrawerListener 设置为您的导航抽屉,并使用 onDrawerStateChanged() 或here 中的一些其他选项来调用 clearFocus() 在您的 RecyclerView 上。

【讨论】:

谢谢,我已经添加了drawerListener,但我无法移除对recyclerView的关注,知道吗? @Delta7 现在这很奇怪...将 android:focusable="true" android:focusableInTouchMode="true" 添加到您的 recyclerView 并重试 它正在聚焦而不是移除焦点:/ 并滚动到顶部 @Delta7 放弃我的最后一条评论...在 onDrawerStateChanged() 上确定设置 recyclerView.setFocusable(false) 这不是最好的方法,但是如果没有,它应该可以工作......遗憾的是我不知道如何提供帮助:/【参考方案4】:

添加android:descendantFocusability="blocksDescendants" 可以限制滚动到recylerview,但是如果你的布局中有edittext,这个属性也可以阻止特定edittext 的焦点。因此,如果您使用此属性,请确保在加载布局后在您的 kotlin/java 类中删除此属性。

parentLayout?.descendantFocusability = FOCUS_BEFORE_DESCENDANTS (view as ViewGroup).descendantFocusability = FOCUS_BEFORE_DESCENDANTS

【讨论】:

【参考方案5】:

只需在您的线性布局中添加以下代码,即可 100% 运行 `android:descendantFocusability="blocksDescendants"

<android.support.v4.widget.NestedScrollView
    android:layout_
    android:layout_/>

    <LinearLayout
        android:descendantFocusability="blocksDescendants"
        android:layout_
        android:layout_>

【讨论】:

以上是关于如何从 ScrollView 内的 RecyclerView 中移除焦点?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ScrollView 内的 LinearLayout 底部放置按钮

带有 DrawerLayout 的 ScrollView 内的 ListView

在 SwiftUI 中,如何通过动态变化的滚动区域来缩放 scrollView 内的内容?

导航控制器内的iOS ScrollView + Page Controller:如何更改每个页面的导航栏标题?

基维。 GridLayout 在 ScrollView 内的位置

解决Android中,禁止ScrollView内的控件改变之后自动滚动 - 转