在RecyclerView上删除项目时没有animation

我第一次使用RecyclerView 。 一切都工作正常,除了没有项目删除animation,即使在项目添加animation工作得很好。

我没有设置任何自定义项目animation师,但根据文档 :

RecyclerView默认启用添加和删除项目的animation。

所以去除animation应该工作。

我想有删除的默认animation,但不能得到这个工作。

这是我如何设置RecyclerView:

 private void setupRecyclerView() { mRecyclerView = (RecyclerView) mRootView.findViewById(R.id.recycler_view); mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); View emptyView = mRootView.findViewById(R.id.empty_view); mAdapter = new RoutineAdapter(getActivity(), mRoutineItems, emptyView); mRecyclerView.setAdapter(mAdapter); } 

这是我的适配器:

 private class RoutineAdapter extends RecyclerView.Adapter<RoutineAdapter.ViewHolder> { private final Context mContext; private List<RoutineItem> mData; private View mEmptyView; public RoutineAdapter(Context context, List<RoutineItem> data, View emptyView) { mContext = context; mData = data; mEmptyView = emptyView; setEmptyViewVisibility(); } public void add(RoutineItem routineItem, int position) { mData.add(position, routineItem); setEmptyViewVisibility(); notifyItemInserted(position); } public void remove(int position){ mData.remove(position); setEmptyViewVisibility(); notifyItemRemoved(position); } public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final View view = LayoutInflater.from(mContext).inflate( R.layout.fragment_routines_list_item, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, final int position) { final RoutineItem routineItem = getItem(position); holder.circle.setBackgroundResource( colorNumberToDrawableResource(routineItem.colorNumber)); holder.initial.setText(routineItem.routineName.substring(0, 1)); holder.routineName.setText(routineItem.routineName); holder.lastTimeDone.setText(routineItem.lastTimeDoneText); if (routineItem.isSelected) { holder.itemView.setBackgroundColor( getResources().getColor(R.color.background_item_selected)); } else { holder.itemView.setBackgroundResource( R.drawable.darker_background_on_pressed); } holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mPresenter.onRoutineClicked(routineItem.routineName); } }); holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { mPresenter.onRoutineLongClicked(routineItem.routineName); return true; } }); } @Override public int getItemCount() { return mData.size(); } public RoutineItem getItem(int position) { return mData.get(position); } private void setEmptyViewVisibility() { if (getItemCount() == 0) { mEmptyView.setVisibility(View.VISIBLE); } else { mEmptyView.setVisibility(View.GONE); } } class ViewHolder extends RecyclerView.ViewHolder { public final View circle; public final TextView initial; public final TextView routineName; public final TextView lastTimeDone; public ViewHolder(View view) { super(view); circle = view.findViewById(R.id.circle); initial = (TextView) view.findViewById(R.id.initial); routineName = (TextView) view.findViewById(R.id.routine_name); lastTimeDone = (TextView) view.findViewById(R.id.last_time_done); } } } 

Fragment_routines_list_item.xml:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:minHeight="@dimen/standard_list_item_height" android:paddingBottom="8dp" android:background="@drawable/darker_background_on_pressed" android:clickable="true"> ...... </RelativeLayout> 

我在做什么错误,导致默认删除animation无法正常工作?

从回收站视图中删除项目的正确方法是从数据集中删除项目,然后告诉适配器该项目被删除

 myDataset.remove(position); // myDataset is List<MyObject> mAdapter.notifyItemRemoved(position); 

解决了它。

问题是,在调用mAdapter.remove(position) ,我的代码的另一部分是调用mAdapter.notifyDataSetChanged() ,我假设停止删除animation。

总而言之,如果在正在进行animation的过程中调用mAdapter.notifyDataSetChanged ,则animation将停止。

使用notifyItemRemoved(position)而不是notifyDataSetChanged()如下所示

 myDataset.remove(position); notifyItemRemoved(position); 

因为notifyDataSetChanged()只是在没有任何animation的情况下通知更新的数据。

另一个不正确的删除animation的原因可能是RecyclerViews高度。 validation高度是match_parent而不是wrap_content

我能够通过animation和更新的索引删除视图,如下所示:

在适配器内,

 public boolean removeItem(int position) { if (data.size() >= position + 1) { data.remove(position); return true; } return false; } 

在删除视图时,请致电

 if (adapter.removeItem(position)) { adapter.notifyItemRemoved(position); adapter.notifyItemRangeChanged(position, adapter.getItemCount()); } 

我已经使用了布尔方法来确保双击等等。 不要导致崩溃。

经过长时间的debugging,我意识到我必须将setHasStableIds(true)添加到我的适配器并实现

 @Override public long getItemId(int position) { return position; } 

之后,删除animation开始工作

我遇到了同样的问题,我通过实施我自己的RecyclerView来解决这个问题,在我的回收查看中,我这样做了:

 public class MyRecyclerView extends RecyclerView { private View mEmptyView; private AdapterDataObserver mDataObserver = new AdapterDataObserver() { public void onChanged() { super.onChanged(); updateEmptyView(); } public void onItemRangeRemoved(int positionStart, int itemCount) { super.onItemRangeRemoved(positionStart, itemCount); updateEmptyView(); } public void onItemRangeInserted(int positionStart, int itemCount) { super.onItemRangeInserted(positionStart, itemCount); updateEmptyView(); } }; // private void setAdapter() {} private void updateEmptyView() { // update empty view's visibility } } 

基本上,当你向/从recyclerview中添加/删除项目时,可以调用notifyItemInserted()/ notifyItemRemoved()和notifyItemRangeChanged(),这些方法将调用onItemRangeRemoved() / onItemRangeInserted() 。 所以在这些方法中,你可以更新空视图的可见性,并且不会破坏animation。