为什么列表和状态列表选择器波纹动画不能完全绘制在 API24 上?

Why does a list and state list selector ripple animation not draw completely on API24?

在这种情况下,问题与 RecyclerView 有关,我希望涟漪效果从手指用自定义颜色触摸到视图的整个范围的地方动画化(如果不完全的话,大致如此),很多就像视图布局方面的列表视图行,最后以另一种颜色选择的行结束其动画。

我有

items_row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/rowLayout"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="horizontal"
  android:paddingBottom="5dp"
  android:paddingTop="5dp"
  android:background="@drawable/items_ripple_state_selector"
  >

  <RelativeLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:gravity="center">

    <TextView
      android:id="@+id/item_unit"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_below="@+id/item_amount"
      android:layout_centerHorizontal="true"
      android:gravity="center"
      android:text="unit" />

    <TextView
      android:id="@+id/item_amount"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentTop="true"
      android:layout_centerHorizontal="true"
      android:gravity="center"
      android:text="amount" />
  </RelativeLayout>

  <RelativeLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="4.6"
    android:gravity="center_vertical">

    <TextView
      android:id="@+id/item_title"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="title"
      android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
      android:id="@+id/item_description"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignLeft="@+id/item_title"
      android:layout_alignWithParentIfMissing="true"
      android:layout_below="@+id/item_title"
      android:text="description" />
  </RelativeLayout>
</LinearLayout>

items_ripple_state_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
    <selector>
      <item android:state_pressed="true" android:drawable="@color/state_activated" />
      <item android:state_selected="true" android:drawable="@color/state_selected" />
      <item android:drawable="@android:color/transparent" />
    </selector>
  </item>
  <item>
    <ripple android:color="@color/primary">
      <item android:id="@android:id/mask">
        <color android:color="@android:color/white" />
      </item>
    </ripple>
  </item>
</layer-list>

测试结果不佳

我在以下设备上进行了测试,其中涟漪效果动画停止得太早,导致更多的是 "blip"/"ping" 而不是完全扩展到视图的边缘。

测试结果良好

我已经在以下设备上进行了测试,其中涟漪效果动画 非常漂亮 我期望的是它的全长,到视图的边缘:

我这辈子都弄不明白这是怎么回事。它在 N6 和 N5X 上看起来很糟糕,因为动画在中途停止,关于动画何时停止没有明显的模式。

我已经阅读了很多 SO 问题以及 RecyclerView、StateListDrawable 和 RippleDrawable 文档,但没有任何内容可以对我所看到的行为做出任何解释。

我最接近的,也就是我目前正在使用的,以及我在这个 post 中分享的代码方面的内容,来自这个答案

有没有人知道为什么会发生这种情况以及如何解决它?

我不知道为什么它在 Marshmallow 中有效,但在 Nougat 中无效的具体原因。但是,最常见的情况是当您看到此问题时,这是因为 RecyclerView 刷新 and/or 重新绑定的方式太多了。

基本上会发生什么

  1. 用户点击
  2. 动画开始
  3. 需要重新绑定该项目
  4. RecyclerView 在项目上调用重新绑定
  5. 动画被取消,因为视图重置。

最常见的情况是调用 RecyclerAdapter#notifyItemChanged(int) 方法或 RecyclerAdapter#notifyDatasetChanged() 次数过多。

如果可能,最好使用RecyclerView.Adapter#notifyItem____方法。 notifyDatasetChanged() 将重新绑定列表中的所有项目。使用 notifyItem_____ 方法将确保仅在需要时更新个别项目。否则,您需要确保仅在数据集中发生实际更改时才调用 nofityDatasetChanged()

另一个常见问题是应用程序是否在 RecyclerViewRecyclerView 的任何父级中调用 invalidate。这将导致整个视图树的刷新,这将需要重新绑定 RecyclerView.

中的所有项目。