RecyclerView.Holder会丢失有关动画的信息(如果它已滚动)(注意它没有被回收)

时间:2018-02-06 19:54:47

标签: android android-recyclerview kotlin

我正在实施一个recyclerview和一个适配器(显然)。在ViewHolders中,我有一个可点击的ImageView。此imageView使用以XML格式完成的动画,可以是“填充心脏”和“未填充的心脏”。启用它时会从下往上填充心脏。当禁用它会打破心脏,心脏会回到“未填充的心脏”。

我如何制作“错误”:

  1. 打开应用
  2. “Heart”我的项目(这会保存在数据库中并在以后每次打开应用程序时加载)。这将激活动画填充心脏,心脏将保持充实。
  3. 如果我只是滚动,我看不到我的项目,然后备份心脏是“未填充”。该项目从未进入回收部分,它只是失去了视力。可以说,“未填充的心脏”是动画的基本状态。
  4. 如果我现在点击心脏,那么“break” - 动画(即unheart)会激活它。但它来自未填充的心 - > break-animation - >未满的心。
  5. 注意:

    1. 我不希望我的“满心”状态因为视线超出“可见度”而回头。
    2. 如果我的视图被回收然后通过绑定返回,那么心脏充满了状态。
    3. 我的RecyclerView.Holder功能。

      fun onTrackClick(tracking : Boolean){
          Log.d(TAG, "Clling onTrack!")
          val stateSet = intArrayOf(android.R.attr.state_checked * if (tracking) 1 else -1)
          btn.setImageState(stateSet, true);
      }
      
      fun bind(item: Media, viewActions: onViewSelectedListener){
          if(item.imgpath.isNotEmpty()){
              image.loadImg("https://image.tmdb.org/t/p/w342/${item.imgpath}") // 342 vs 500
          }
      
          id = item.tmdbid
          viewActions.getSingleMedia(item.tmdbid)
                  ?.observeOn(AndroidSchedulers.mainThread())
                  ?.subscribeOn(Schedulers.io())
                  ?.subscribe({ singleMedia ->
                      onTrackClick(true)
                      tracking = true}, {throwable -> onTrackClick(false)})
          Log.d(TAG, "In here for ${item.tmdbid}")
          title.text = item.name
          rating.text = "${item.rating}"
      
          btn.setOnClickListener {
              viewActions.onTracking(item)
              tracking = !tracking
              onTrackClick(tracking)
          }
          super.itemView.setOnClickListener { viewActions.onItemSelected(item)}   // Only need ID.
      }
      

      然后我的ImageView变得动画了:

      <ImageView
          android:id="@+id/img_button_tracker_media_item"
          android:layout_width="32dp"
          android:layout_height="32dp"
          android:layout_marginStart="8dp"
          android:adjustViewBounds="true"
          android:background="@android:color/transparent"
          android:scaleType="center"
          android:transitionName="HEART"
          android:src="@drawable/asl_trimclip_heart"
          app:layout_constraintBottom_toBottomOf="@+id/rating"
          app:layout_constraintEnd_toEndOf="@+id/imageView"
          app:layout_constraintHorizontal_bias="1.0"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="@+id/rating"
          app:layout_constraintVertical_bias="0.52" />
      

      动画:

          <animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
      
        <item
          android:id="@+id/liked"
          android:drawable="@drawable/vd_trimclip_heart_full"
          android:state_checked="true"/>
      
        <item
          android:id="@+id/not_liked"
          android:drawable="@drawable/vd_trimclip_heart_empty"/>
      
        <transition
          android:drawable="@drawable/avd_trimclip_heart_fill"
          android:fromId="@id/not_liked"
          android:toId="@id/liked"/>
      
        <transition
          android:drawable="@drawable/avd_trimclip_heart_break"
          android:fromId="@id/liked"
          android:toId="@id/not_liked"/>
      
      </animated-selector>
      

      提前致谢!

2 个答案:

答案 0 :(得分:1)

猜猜你更喜欢50%的答案而没有答案,所以这是我的2美分:

您的数据有两种状态:心脏充盈,心脏未充满。这两个状态应该通过显示不同的可绘制资源反映在View中。

所以基本上你必须在View实现中使用两种RecyclerView.Adapter类型。为此,您需要覆盖getItemViewType()并返回当前状态的正确视图类型,并在onCreateViewHolder()中根据View类型设置可绘制资源。

如果你&#34;心脏&#34;或者&#34; unheart&#34;一个RecyclerView项,其状态必须改变。您已经在更新基础数据(否则在View被回收后状态将无法正确显示)。所以剩下要做的就是在notifyItemChanged()上致电RecyclerView.Adapter。要么推迟到动画完成后(例如在android.os.Handler实例上使用postDelayed()方法),要么尝试实现自己的RecyclerView.ItemAnimator(但只有在其他方法看起来很糟糕时才会这样做)闪烁的drawables)

答案 1 :(得分:1)

我会说你的问题实际上并没有设置最终的填充状态,只要你在RecyclerView中有两个状态,你就不要忘记设置“特殊”情况(在这种情况下,心满意足) )。

意思是,如果检查模型的值,则必须始终设置当前状态,一个简单的例子是:

onBindViewHolder(..) {
  // The View.GONE is the easly forgot state
  imageView.visibility = if(someModel.isShowImageView()) View.VISIBLE else View.GONE) 
}

简单地说,完成动画后,您应该将imageView设置为最终状态(填充心脏),否则当动画重置(视图外)时,您将显示初始状态。