使用 swipelayout 动画冻结

Animation freeze with swipelayout

添加 2 个新功能(滑动布局 + 动画)后,我的 ui 冻结了。

我有一个包含电影对象的回收视图。如果我 add/remove/modify 一部电影,我会调用我的电影管理器,因为有一个通知概念(所有想要使用数据的视图都必须在该管理器上注册)。 在我添加新功能之前,这一切都很好。

我使用这个滑动布局: https://github.com/daimajia/AndroidSwipeLayout

目前的项目是这样的:

滑动后:

如果我有 4 个项目,冻结总是可以重现的。我轻扫第二个项目并将其删除。然后它会像我想要的那样消失。 在我滑动 "new" 第二个项目后,会有大约 10-15 秒的冻结。

项目的布局xml:

<com.daimajia.swipe.SwipeLayout
    android:id="@+id/item_movie_swipe_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:id="@+id/item_movie_swipe_bottom_wrapper"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:background="#ff0000">

            <TextView
                android:id="@+id/item_movie_bottom_delete_desc"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawableTop="@drawable/ic_delete_white_24dp"
                android:text="@string/delete"
                android:textColor="#fff"
                android:layout_gravity="center"
                android:padding="10dp"/>
        </LinearLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="5dp">

        <ImageView
            android:id="@+id/item_movie_list_poster"
            style="@style/image_border_style"
            android:layout_width="68dp"
            android:layout_height="100dp"
            android:layout_marginRight="3dp"
            android:background="@android:color/black"/>

        <TextView
            android:id="@+id/item_movie_list_name_year"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_marginBottom="3dp"
            android:layout_toEndOf="@+id/item_movie_list_poster"
            android:layout_toRightOf="@+id/item_movie_list_poster"
            android:gravity="center|left"
            android:padding="3dp" android:text="name"/>

        <TextView
            android:id="@+id/item_movie_list_genre"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:layout_below="@+id/item_movie_list_name_year"
            android:layout_marginBottom="3dp"
            android:layout_toEndOf="@+id/item_movie_list_poster"
            android:layout_toRightOf="@+id/item_movie_list_poster"
            android:padding="3dp"
            android:text="Drama - Komödie - Action" android:textColor="@color/item_textyear"
            android:textSize="12dp"/>

        <TextView
            android:id="@+id/item_movie_list_viewed"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@id/item_movie_list_poster"
            android:layout_toRightOf="@+id/item_movie_list_poster"
            android:paddingLeft="3dp" android:text="Gesehen: "
            android:textColor="@color/accept"
            android:textSize="12dp"/>
    </RelativeLayout>
</com.daimajia.swipe.SwipeLayout>

适配器相关代码:

  @Override
  public void onBindViewHolder(final CDMMoviesAdapter.IC_ViewHolder p_Holder, final int p_iPosition) {

    // more unimportant code...

    p_Holder.m_SwipeLayout.setShowMode(SwipeLayout.ShowMode.PullOut);

    // Drag From Right
    p_Holder.m_SwipeLayout.addDrag(SwipeLayout.DragEdge.Right, p_Holder.m_SwipeLayout.findViewById(R.id.item_movie_swipe_bottom_wrapper));

    // Handling different events when swiping
    p_Holder.m_SwipeLayout.addSwipeListener(new SwipeLayout.SwipeListener() {
      @Override
      public void onClose(SwipeLayout layout) {
        //when the SurfaceView totally cover the BottomView.
      }

      @Override
      public void onUpdate(SwipeLayout layout, int leftOffset, int topOffset) {
        //you are swiping.
      }

      @Override
      public void onStartOpen(SwipeLayout layout) {

      }

      @Override
      public void onOpen(SwipeLayout layout) {
        //when the BottomView totally show.
      }

      @Override
      public void onStartClose(SwipeLayout layout) {

      }

      @Override
      public void onHandRelease(SwipeLayout layout, float xvel, float yvel) {
        //when user's hand released.
      }
    });

    p_Holder.m_SwipeLayout.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View p_View) {
        if((((SwipeLayout) p_View).getOpenStatus() == SwipeLayout.Status.Close)) {
          Intent l_Intent = new Intent();
          Bundle l_Bundle = new Bundle();
          l_Bundle.putLong(CDMMovieDetailsActivity.ARG_MOVIE, l_MovieID);
          l_Intent.putExtras(l_Bundle);
          l_Intent.setClass(l_Context, CDMMovieDetailsActivity.class);
          l_Context.startActivity(l_Intent);
        }
      }
    });

    p_Holder.m_tvDelete.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View p_View) {
        Animation l_DeleteAnimation = AnimationUtils.loadAnimation(l_Context, R.anim.slide_out);
        l_DeleteAnimation.setAnimationListener(new Animation.AnimationListener() {
          @Override
          public void onAnimationStart(Animation animation) {
          }

          @Override
          public void onAnimationRepeat(Animation animation) {
          }

          @Override
          public void onAnimationEnd(Animation animation) {
            mItemManger.removeShownLayouts(p_Holder.m_SwipeLayout);
            CDMMovieManager.getInstance().removeMovieID(m_List, m_MovieIDs.get(p_iPosition));
            mItemManger.closeAllItems();
          }
        });

        p_Holder.m_View.startAnimation(l_DeleteAnimation);
      }
    });

    // mItemManger is member in RecyclerSwipeAdapter Class
    mItemManger.bindView(p_Holder.itemView, p_iPosition);

    // more unimportant code...
  }

  /**
   * This class is the viewholder. For internal use only.
   */
  public static class IC_ViewHolder extends RecyclerView.ViewHolder {

    /**
     * Constructor
     *
     * @param p_View the view
     */
    public IC_ViewHolder(View p_View) {
      super(p_View);

      m_View = p_View;
      m_SwipeLayout = (SwipeLayout) p_View.findViewById(R.id.item_movie_swipe_layout);

      m_tvNameYear = (TextView) p_View.findViewById(R.id.item_movie_list_name_year);
      m_ivPoster = (ImageView) p_View.findViewById(R.id.item_movie_list_poster);
      m_tvGenre = (TextView) p_View.findViewById(R.id.item_movie_list_genre);
      m_tvViewed = (TextView) p_View.findViewById(R.id.item_movie_list_viewed);

      m_tvDelete = (TextView) p_View.findViewById(R.id.item_movie_bottom_delete_desc);
    }

    public View m_View;
    public SwipeLayout m_SwipeLayout;

    public TextView m_tvNameYear;
    public ImageView m_ivPoster;
    public TextView m_tvGenre;
    public TextView m_tvViewed;

    public TextView m_tvDelete;
  }

CDMMovieManager.getInstance().removeMovieID(m_List, m_MovieIDs.get(p_iPosition)); 中,电影将被删除并通知所有已注册的观看次数。在这种情况下,此适配器的片段将调用 m_Adapter.notifyDataSetChanged();

动画文件:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="250"
        android:fromXDelta="0%"
        android:toXDelta="-100%"/>
</set>

我试过 View.clearAnimation()Animation.setAnimationListener(null) 之类的东西,但我总是遇到这个问题。 请询问您是否需要更多信息。

更新:

仅当我尝试滑动下一个项目时才会出现问题。 (例如删除第二项。之后尝试滑动第三项,这是新的第二项 -> 冻结我尝试滑动的项目)。只有在任何其他项目上滑动才能解除冻结。

我解决了我的问题。这个答案对我有帮助:How to animate RecyclerView items when they appear

我将此代码添加到我的适配器中:

@Override
public void onViewDetachedFromWindow(IC_ViewHolder p_Holder) {
  p_Holder.m_View.clearAnimation();
}