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

Android 为什么列表和状态列表选择器ripple动画不能完全在API24上绘制?,android,android-recyclerview,rippledrawable,statelistdrawable,Android,Android Recyclerview,Rippledrawable,Statelistdrawable,在本例中,问题与RecyclerView有关,我希望涟漪效果能够从手指接触自定义颜色的位置到视图的整个范围进行动画制作(如果不是精确的话),就像视图布局中的listview行一样,最后用另一种颜色选择的行结束动画 我有 items\u row.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" a

在本例中,问题与RecyclerView有关,我希望涟漪效果能够从手指接触自定义颜色的位置到视图的整个范围进行动画制作(如果不是精确的话),就像视图布局中的listview行一样,最后用另一种颜色选择的行结束动画

我有

items\u 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>
<?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>

items\u ripple\u state\u selector.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>
<?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>

结果不佳的测试

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

  • Nexus 6、牛轧糖(7.0.0)、API 24
  • Nexus 5X,牛轧糖(7.x.x),非100%小版本
  • 针对API级别24的不同AVD
测试结果良好

我已经在以下设备上进行了测试,其中涟漪效果动画的动画效果非常漂亮,我希望它的整个长度都能达到视图的边缘:

  • Nexus 5,棉花糖(6.0.1),API等级23
  • Nexus 4,棒棒糖(5.1.1),API等级22
我一辈子都搞不清楚这到底是怎么回事。在N6和N5X上,当动画中途停止时,它看起来非常可怕,没有关于动画何时停止的明显模式

我已经阅读了很多SO问题以及RecyclerView、StateListDrawable和RippleDrawable文档,但是没有任何东西可以解释我看到的行为

我所得到的最接近的答案,就是我目前正在使用的,以及我在这篇文章中分享的代码,来自于这个答案


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

我不知道为什么它在棉花糖中有效,但在牛轧糖中无效。然而,当您看到这个问题时,最常见的原因是
RecyclerView
太过刷新和/或重新绑定

基本上会发生的是

  • 用户点击
  • 动画开始
  • 有件事要求重新绑定该项目
  • RecyclerView对项目调用重新绑定
  • 由于视图重置,动画被取消
  • 最常见的情况是调用
    RecyclerAdapter\notifyItemChanged(int)
    方法或
    RecyclerAdapter\notifyDatasetChanged()
    太多次时会发生这种情况

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


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

    中的所有项目。我不知道明确的答案,但我知道如果RecyclerView绑定太多,这是非常常见的情况。这是由于在适配器上调用
    notifyItem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。使这个问题更难找出问题的根源的原因是,相同的代码只在几个API级别的缺口上工作。这可能更像是一个更大问题的症状。我怀疑现在的情况是,RecyclerView再次将项目绑定到相同的项目上。看起来项目没有改变,但是所有的动画都会重置。是的,你把钉子钉在了这个项目的头上!我在ContentProvider中注释掉了notifyChange调用,它将光标馈送给RecyclerView,而涟漪效应现在正像我所期望的那样产生动画效果。如果你想发表你的评论或类似的回答,我很乐意接受。棘手的调试,这一个!嗯,修复它会更困难,因为如果数据集被更新,您仍然需要这些通知。否则,您的RecyclerView将过时(或者有时会出现异常)。