Recyclerview在Android中notifyItemChanged后防止触摸事件

Posted

技术标签:

【中文标题】Recyclerview在Android中notifyItemChanged后防止触摸事件【英文标题】:Recyclerview preventing touch events after notifyItemChanged in Android 【发布时间】:2020-10-03 02:20:56 【问题描述】:

Recyclerview 有一个ViewHolder,通常包含TextView。文本内容是可选择的,当长按文本打开选择菜单时。 notifyItemChanged 函数从Adapter 外部调用以调整Textview 字体的大小。调整大小之前可用的文本选择菜单,但之后无法选择项目。长按时不要打开文本选择菜单。没有任何请求不允许事件,但问题出现在notifyItemChanged 之后。

编辑:

问题是Recyclerview的那个item view的TextView xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textRow"
    android:layout_
    android:layout_
    android:textIsSelectable="true"
    android:textSize="15sp" />

问题是解决如果TextViewandroid:layout_widthWRAP_CONTENT,但一定是MATCH_PARENT,这有什么关系?

回收站视图:

<androidx.drawerlayout.widget.DrawerLayout
    android:id="@+id/drawerLayout"
    android:layout_
    android:layout_
    tools:context=".activity.ReadBookActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_
        android:layout_ />

</androidx.drawerlayout.widget.DrawerLayout>

Edit-2:

我所有的文本内容都包含许多跨度,并且字体大小有 RelativeSizeSpan。更改字体大小时正在编辑。并使用notifyItemChanged(i) 通知该项目。使用notifyDataSetChanged() 而不在项目中使用Wrap_Content 时不会出现此问题。

Edit-3:问题源于完全编辑RelativeSizeSpan,因为它在更改字体大小时更新为新大小。去掉了更新,现在用的是Textview.setTextSize(),没问题。

【问题讨论】:

请发布一个最小可重复的例子 【参考方案1】:

因此,阅读DrawerLayout 的文档时明确指出:

要使用 DrawerLayout,请将您的主要内容视图定位为第一个 宽度和高度为 match_parent 且没有 的孩子。 在主要内容视图之后添加抽屉作为子视图并设置 layout_gravity 适当。抽屉通常使用 match_parent 高度和固定宽度。

所以基本上你的DrawerLayout 不能只包含 1 个视图,它需要首先有你的主要内容,然后是你的 RecyclerView 或其他任何东西,RecyclerView 需要有一个固定的宽度或可能是 wrap_contentRecyclerView 中的项目现在可以是任何你想要的。

这是一个例子:

activity_main.xml:(注意 RecyclerView 不是第一项,它的 layout_width 为 wrap_content

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/drawer_layout"
    android:layout_
    android:layout_
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_
        android:layout_ />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_
        android:layout_ />

</androidx.drawerlayout.widget.DrawerLayout>

app_bar_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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_
    tools:context=".MainActivity">

    <include layout="@layout/content_main" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/main_fab"
        android:layout_
        android:layout_
        android:layout_gravity="bottom|right|end"
        android:layout_margin="16dp"
        android:elevation="@dimen/elevation"
        app:srcCompat="@drawable/ic_add" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

content_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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_
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/app_bar_main">

    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_
        android:layout_
        app:defaultNavHost="true"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

我自己并没有实际测试过这个,但它应该可以工作,因为我的设置完全相同.

【讨论】:

(旁白:在渲染inline code时,请注意,您可以使用单反引号,并且不需要三重反引号,尽管三元组确实可以工作。三元组仅用于块格式化。它是尽可能使用单曲是理想的,因为这使材料更容易编写和编辑)。

以上是关于Recyclerview在Android中notifyItemChanged后防止触摸事件的主要内容,如果未能解决你的问题,请参考以下文章

如何在android的Recyclerview中显示更多[重复]

android中RecyclerView嵌套RecyclerView中,如何为内层RecyclerView设值的问题

在recyclerview项目android中更改视图之间的焦点

Android - 网格中项目之间的 RecyclerView 间距

在 RecyclerView 中获取一行的宽度和高度 - Android

Android:以编程方式在片段中添加多个 RecyclerView