Android 在RecyclerView上删除项目时没有动画
我第一次使用了Android 在RecyclerView上删除项目时没有动画,android,android-recyclerview,Android,Android Recyclerview,我第一次使用了RecyclerView。一切正常,除了没有关于项目移除的动画,即使项目添加的动画工作正常 我没有设置任何自定义项animator,但根据: 默认情况下,用于添加和删除项目的动画在RecyclerView中启用 所以移除时的动画应该可以工作 我想在删除时使用默认动画,但无法使其正常工作 以下是我设置RecyclerView的方式: private void setupRecyclerView() { mRecyclerView = (RecyclerView) mRootVie
RecyclerView
。一切正常,除了没有关于项目移除的动画,即使项目添加的动画工作正常
我没有设置任何自定义项animator,但根据:
默认情况下,用于添加和删除项目的动画在RecyclerView
中启用
所以移除时的动画应该可以工作
我想在删除时使用默认动画,但无法使其正常工作
以下是我设置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);
}
}
}
私有类RoutineAdapter
扩展RecyclerView.Adapter{
私有最终上下文mContext;
私有列表数据;
私有视图mEmptyView;
公共RoutineAdapter(上下文、列表数据、视图emptyView){
mContext=上下文;
mData=数据;
mEmptyView=emptyView;
setEmptyView可见性();
}
公共无效添加(RoutineItem RoutineItem,内部位置){
mData.add(位置、路线项目);
setEmptyView可见性();
(位置);
}
公共无效删除(内部位置){
mData.remove(位置);
setEmptyView可见性();
已移除(位置)的项目;
}
public ViewHolder onCreateViewHolder(视图组父级,int-viewType){
最终视图=布局更平坦。从(mContext)。充气(
R.layout.fragment_例程_列表_项,父项,false);
返回新的ViewHolder(视图);
}
@凌驾
公共无效onBindViewHolder(ViewHolder,最终int位置){
最终RoutineItem RoutineItem=getItem(位置);
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));
}否则{
holder.itemView.setBackgroundResource(
R.可绘制。背景颜色较深(按下);
}
holder.itemView.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
mPresenter.onRoutineClicked(routineItem.routineName);
}
});
holder.itemView.setOnLongClickListener(新视图.OnLongClickListener(){
@凌驾
仅长按公共布尔值(视图v){
mPresenter.onRoutineOngClicked(routineItem.routineName);
返回true;
}
});
}
@凌驾
public int getItemCount(){
返回mData.size();
}
公共RoutineItem getItem(内部位置){
返回mData.get(位置);
}
私有void setEmptyViewVisibility(){
如果(getItemCount()==0){
mEmptyView.setVisibility(View.VISIBLE);
}否则{
mEmptyView.setVisibility(View.GONE);
}
}
类ViewHolder扩展了RecyclerView.ViewHolder{
公众最终意见圈;
公开最终文本视图首字母;
公共最终文本视图routineName;
公共最终文本视图lastTimeDone;
公共视图持有者(视图){
超级(视图);
圆圈=view.findViewById(R.id.circle);
initial=(TextView)view.findViewById(R.id.initial);
routineName=(TextView)view.findViewById(R.id.routine\u name);
lastTimeDone=(TextView)view.findViewById(R.id.last\u time\u done);
}
}
}
片段\u例程\u列表\u 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>
......
我做错了什么导致默认删除动画无法工作?解决了这个问题
问题是,在调用mAdapter.remove(position)
之后,我的代码的另一部分正在调用mAdapter.notifyDataSetChanged()
,我假设它会停止删除动画
总之,如果在动画正在进行时调用
mAdapter.notifyDataSetChanged
,动画将停止。我遇到了同样的问题,我通过实现自己的RecyclerView解决了这个问题,在我的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(),这些方法将在
mDataObserver
中调用onItemRangeRemoved()
。因此,在这些方法中,您可以更新空视图的可见性,并且它不会破坏动画 从recycler视图中删除项目的正确方法是从数据集中删除该项目,然后告诉适配器该项目已按此方式删除
myDataset.remove(position); // myDataset is List<MyObject>
mAdapter.notifyItemRemoved(position);
myDataset.remove(位置);//myDataset是一个列表
mAdapter.notifyItemRemoved(位置);
我可以删除带有动画的视图,并更新索引,如下所示:
在适配器中
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());
}
我使用了一种布尔方法来确保双击等不会导致崩溃。使用
notifyItemRemoved(position)
而不是下面的notifyDataSetChanged()
myDataset.remove(position);
notifyItemRemoved(position);
因为
notifyDataSetChanged()
只是通知更新的数据,而没有任何动画。移除动画工作不正常的另一个原因可能是RecyclerViews
高度。验证高度是否为匹配父项
,而不是包裹内容
经过长时间的调试,我意识到我必须将setHasStableIds(true)
添加到适配器并实现
@Override
public long getItemId(int position) {
return position;
}
之后,remove animation开始工作很晚,但可能对需要{search items with animation}的人有所帮助 在活动或片段中使用以下代码,其中
yourAdapter.animateTo(filteredModelList);
在您的RecyclerAdapter类中使用以下代码
public void animateTo(List<CommonModel> models) {
applyAndAnimateRemovals(models);
applyAndAnimateAdditions(models);
applyAndAnimateMovedItems(models);
}
private void applyAndAnimateRemovals(List<CommonModel> newModels) {
for (int i = items.size() - 1; i >= 0; i--) {
final CommonModel model = items.get(i);
if (!newModels.contains(model)) {
removeItem(i);
}
}
}
private void applyAndAnimateAdditions(List<CommonModel> newModels) {
for (int i = 0, count = newModels.size(); i < count; i++) {
final CommonModel model = newModels.get(i);
if (!items.contains(model)) {
addItem(i, model);
}
}
}
private void applyAndAnimateMovedItems(List<CommonModel> newModels) {
for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
final CommonModel model = newModels.get(toPosition);
final int fromPosition = items.indexOf(model);
if (fromPosition >= 0 && fromPosition != toPosition) {
moveItem(fromPosition, toPosition);
}
}
}
private CommonModel removeItem(int position) {
final CommonModel model = items.remove(position);
notifyItemRemoved(position);
return model;
}
private void addItem(int position, CommonModel model) {
items.add(position, model);
notifyItemInserted(position);
}
private void moveItem(int fromPosition, int toPosition) {
final CommonModel model = items.remove(fromPosition);
items.add(toPosition, model);
notifyItemMoved(fromPosition, toPosition);
}
public void animateTo(列出模型){
应用数据删除(模型);
应用