使用ListAdapter的android recyclerview中缺少默认动画

使用ListAdapter的android recyclerview中缺少默认动画,android,android-recyclerview,android-animation,android-databinding,android-listadapter,Android,Android Recyclerview,Android Animation,Android Databinding,Android Listadapter,我正在使用recyclerview和扩展ListAdapter的适配器。我正在通过调整提交列表来更新内容。但每次内容更新(例如删除一个项目)时,recyclerview都会消失一秒钟,并与更新的内容一起重新出现。有两件事我不喜欢:第一是闪烁,第二是缺少默认动画 如何修复并显示平滑默认动画 适配器: public class AdapterFlightRecords extends ListAdapter<FlightRecordListItem, RecyclerView.ViewHold

我正在使用recyclerview和扩展ListAdapter的适配器。我正在通过调整提交列表来更新内容。但每次内容更新(例如删除一个项目)时,recyclerview都会消失一秒钟,并与更新的内容一起重新出现。有两件事我不喜欢:第一是闪烁,第二是缺少默认动画

如何修复并显示平滑默认动画

适配器:

public class AdapterFlightRecords extends ListAdapter<FlightRecordListItem, RecyclerView.ViewHolder> {

    private FlightRecordListItem mRecentlyDeletedItem;
    private int mRecentlyDeletedItemPosition;

    private class ViewHolderFlightRecord extends RecyclerView.ViewHolder {
        private RvItemFlightRecordsBinding binding;

        private ViewHolderFlightRecord(final RvItemFlightRecordsBinding binding) {
            super(binding.getRoot());
            this.binding = binding;
        }

        private void bind(final EntityFlightRecord flightRecord){
            binding.setFlightRecord(flightRecord);
            binding.executePendingBindings();
        }
    }

    public class ViewHolderDate extends RecyclerView.ViewHolder {
        private RvItemFlightRecordsDateBinding binding;

        private ViewHolderDate(final RvItemFlightRecordsDateBinding binding) {
            super(binding.getRoot());
            this.binding = binding;
        }

        private void bind(final DateFlightRecordsListItem item){
            OffsetDateTime date = item.getDate();
            binding.setYearMonth(YearMonth.from(date));
            binding.executePendingBindings();
        }
    }

    public AdapterFlightRecords(){
        super(new FlightRecordsDiffCallback());
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        switch(viewType){
            case 1:
                return new ViewHolderDate(RvItemFlightRecordsDateBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
            case 2:
                return new ViewHolderFlightRecord(RvItemFlightRecordsBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
            default:
                throw new RuntimeException("No such viewType");
        }

        //return new ViewHolderFlightRecord(RvItemFlightRecordsBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        switch(holder.getItemViewType()){
            case 1:
                DateFlightRecordsListItem date = (DateFlightRecordsListItem) getItem(position);
                ((ViewHolderDate) holder).bind(date);
                break;
            case 2:
                EntityFlightRecord flightRecord = (EntityFlightRecord) getItem(position);
                ((ViewHolderFlightRecord) holder).bind(flightRecord);
                holder.itemView.setTag(flightRecord);
                break;
        }
    }

    @Override
    public int getItemViewType(int position) {
        // Just as an example, return 0 or 2 depending on position
        // Note that unlike in ListView adapters, types don't have to be contiguous
        return getItem(position).getType().getValue();
    }

    public EntityFlightRecord getItemFromList(int position){
            return (EntityFlightRecord) getItem(position);
    }

    /*private View.OnClickListener createOnClickListener(int id) {
        return view -> {
            QuestionnaireFragmentDirections.ActionQuestionnaireFragmentToSubjectFragment action = QuestionnaireFragmentDirections.actionQuestionnaireFragmentToSubjectFragment(id);
            Navigation.findNavController(view).navigate(action);
        };
    }*/
}

class FlightRecordsDiffCallback extends DiffUtil.ItemCallback<FlightRecordListItem> {

    @Override
    public boolean areItemsTheSame(@NonNull FlightRecordListItem oldItem, @NonNull FlightRecordListItem newItem) {
        //TODO implement equals and hashcode in Questionnaire
        return false;
        //return oldItem.id == newItem.id;
    }

    @Override
    public boolean areContentsTheSame(@NonNull FlightRecordListItem oldItem, @NonNull FlightRecordListItem newItem) {
        //TODO implement equals and hashcode in Questionnaire
        return false;
        //return oldItem.equals(newItem);
    }
}
SwipeToDeleteCallback:

public class SwipeToDeleteCallback extends ItemTouchHelper.SimpleCallback {

private Drawable icon;
private ColorDrawable background;
private OnItemSwipeListener onItemSwipeListener;
private boolean swipeEnabled;

private SwipeToDeleteCallback(int dragDirs, int swipeDirs) {
    super(dragDirs, swipeDirs);
}

private SwipeToDeleteCallback(Builder builder) {
    this(builder.dragDirs, builder.swipeDirs);
    background = builder.bgColorSwipe;
    icon = builder.drawableSwipe;
    swipeEnabled = builder.swipeEnabled;
    onItemSwipeListener = builder.onItemSwipeListener;
}

@Override public boolean isItemViewSwipeEnabled() {
    return swipeEnabled;
}

@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    if (viewHolder instanceof AdapterFlightRecords.ViewHolderDate) return 0;
    return super.getSwipeDirs(recyclerView, viewHolder);
}

@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    return false;
}

@Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    int position = viewHolder.getAdapterPosition();
    onItemSwipeListener.onItemSwiped(position);
}

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);

    View itemView = viewHolder.itemView;
    int backgroundCornerOffset = 20; //so background is behind the rounded corners of itemView

    int iconMargin = (itemView.getHeight() - icon.getIntrinsicHeight()) / 2;
    int iconTop = itemView.getTop() + (itemView.getHeight() - icon.getIntrinsicHeight()) / 2;
    int iconBottom = iconTop + icon.getIntrinsicHeight();

    if (dX > 0) { // Swiping to the right
        int iconLeft = itemView.getLeft() + iconMargin;
        int iconRight = itemView.getLeft() + icon.getIntrinsicWidth() + iconMargin;
        icon.setBounds(iconLeft, iconTop, iconRight, iconBottom);

        background.setBounds(itemView.getLeft(), itemView.getTop(),
                itemView.getLeft() + ((int) dX) + backgroundCornerOffset, itemView.getBottom());
    } else if (dX < 0) { // Swiping to the left
        int iconLeft = itemView.getRight() - iconMargin - icon.getIntrinsicWidth();
        int iconRight = itemView.getRight() - iconMargin;
        icon.setBounds(iconLeft, iconTop, iconRight, iconBottom);

        background.setBounds(itemView.getRight() + ((int) dX) - backgroundCornerOffset,
                itemView.getTop(), itemView.getRight(), itemView.getBottom());
    } else { // view is unSwiped
        background.setBounds(0, 0, 0, 0);
    }

    background.draw(c);
    icon.draw(c);
}

public interface OnItemSwipeListener {
    void onItemSwiped(int position);
}

public static final class Builder {
    private int dragDirs, swipeDirs;
    private Drawable drawableSwipe;
    private ColorDrawable bgColorSwipe;
    private OnItemSwipeListener onItemSwipeListener;
    private boolean swipeEnabled;

    public Builder(int dragDirs, int swipeDirs) {
        this.dragDirs = dragDirs;
        this.swipeDirs = swipeDirs;
    }

    public Builder drawableSwipe(Drawable val) {
        drawableSwipe = val;
        return this;
    }

    public Builder bgColorSwipe(ColorDrawable val) {
        bgColorSwipe = val;
        return this;
    }

    public Builder onItemSwipeListener(OnItemSwipeListener val) {
        onItemSwipeListener = val;
        return this;
    }

    public Builder setSwipeEnabled(boolean val) {
        swipeEnabled = val;
        return this;
    }

    public SwipeToDeleteCallback build() {
        return new SwipeToDeleteCallback(this);
    }
}
}
公共类SwipeToDeleteCallback扩展了ItemTouchHelper.SimpleCallback{
私人绘图图标;
私人彩色背景;
私有OnItemSwipeListener OnItemSwipeListener;
私有布尔可交换;
专用SwipeToDeleteCallback(int-dragDirs、int-swipeDirs){
超级(dragDirs、swipeDirs);
}
专用SwipeToDeleteCallback(生成器生成器){
这(builder.dragDirs、builder.swipiders);
背景=builder.bgColorSwipe;
icon=builder.drawableSwipe;
SwipEnabled=builder.SwipEnabled;
onItemSwipeListener=builder.onItemSwipeListener;
}
@重写公共布尔值IsItemViewSwipEnabled(){
返回开关已启用;
}
@凌驾
public int getSwipeDirs(RecyclerView RecyclerView,RecyclerView.ViewHolder ViewHolder){
if(AdapterLightRecords.ViewHolderDate的viewHolder实例)返回0;
返回super.getswipiders(recyclerView、viewHolder);
}
@凌驾
公共布尔onMove(RecyclerView RecyclerView、RecyclerView.ViewHolder ViewHolder、RecyclerView.ViewHolder目标){
返回false;
}
@覆盖已擦除的公共void(RecyclerView.ViewHolder ViewHolder,int方向){
int position=viewHolder.getAdapterPosition();
onItemSwipeListener.onItemSwiped(位置);
}
@凌驾
public void onChildraw(画布c、RecyclerView RecyclerView、RecyclerView.ViewHolder ViewHolder、float dX、float dY、int actionState、boolean isCurrentlyActive){
super.onchildraw(c、recyclerView、viewHolder、dX、dY、actionState、isCurrentlyActive);
View itemView=viewHolder.itemView;
int backgroundCornerOffset=20;//因此背景位于itemView的圆角后面
int iconMargin=(itemView.getHeight()-icon.getIntrinsicHeight())/2;
int iconTop=itemView.getTop()+(itemView.getHeight()-icon.getIntrinsicHeight())/2;
int iconBottom=iconTop+icon.getIntrinsicHeight();
如果(dX>0){//向右滑动
int iconLeft=itemView.getLeft()+iconMargin;
int iconRight=itemView.getLeft()+icon.getIntrinsicWidth()+iconMargin;
icon.setBounds(iconLeft、iconTop、iconRight、iconBottom);
background.setBounds(itemView.getLeft(),itemView.getTop(),
itemView.getLeft()+((int)dX)+backgroundCornerOffset,itemView.getBottom());
}如果(dX<0){//向左滑动,则为else
int iconLeft=itemView.getRight()-iconMargin-icon.getIntrinsicWidth();
int iconRight=itemView.getRight()-iconMargin;
icon.setBounds(iconLeft、iconTop、iconRight、iconBottom);
background.setBounds(itemView.getRight()+((int)dX)-backgroundCornerOffset,
itemView.getTop()、itemView.getRight()、itemView.getBottom());
}否则{//视图将不被擦除
背景.背景(0,0,0,0);
}
背景图(c);
图标绘制(c);
}
公共接口侦听器{
无效(内部位置);
}
公共静态最终类生成器{
私人内特德拉格迪尔、瑞士人;
私人提款刷卡;
私人彩绘bgColorSwipe;
私有OnItemSwipeListener OnItemSwipeListener;
私有布尔可交换;
公共建筑商(国际德拉格迪尔、国际瑞士){
this.dragDirs=dragDirs;
this.swipiders=swipiders;
}
公共生成器可提取滑动(可提取val){
drawableSwipe=val;
归还这个;
}
公共生成器bgColorSwipe(可着色val){
bgColorSwipe=val;
归还这个;
}
公共生成器onItemSwipeListener(onItemSwipeListener val){
mswipelistener=val;
归还这个;
}
公共生成器已启用(布尔值){
SwipEnabled=val;
归还这个;
}
公共SwipeToDeleteCallback生成(){
返回新的SwipeToDeleteCallback(此);
}
}
}
我猜一定有任何一行代码会抑制默认动画,但是在哪里呢

我找到了此线程,但没有解决我的问题:

对照我的代码检查您的代码后,FlightRecordsDiffCallback类中出现问题 尝试在代码中取消对return语句的注释,并删除默认值-return false。 在我的代码中-动画无法正常工作,因为我经常在两个返回状态之间混合:

@Override
公共布尔项相同(…)

@覆盖
公共布尔值的内容相同(…)

这让我检查了你的代码,我认为问题在于,你使用return false,而不是在newItem和oldItem之间创建一个布尔返回。
@BindingAdapter(value = {"swipeEnabled", "drawableSwipe", "bgColorSwipe", "onItemSwipe"}, requireAll = false)
    public static void setItemSwipeToRecyclerView(RecyclerView recyclerView, boolean swipeEnabled, Drawable drawableSwipe, ColorDrawable bgColorSwipe,
                                                  SwipeToDeleteCallback.OnItemSwipeListener onItemSwipe) {

        ItemTouchHelper.Callback swipeCallback = new SwipeToDeleteCallback
                .Builder(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT)
                .bgColorSwipe(bgColorSwipe)
                .drawableSwipe(drawableSwipe)
                .setSwipeEnabled(swipeEnabled)
                .onItemSwipeListener(onItemSwipe)
                .build();

        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(swipeCallback);
        itemTouchHelper.attachToRecyclerView(recyclerView);
    }
public class SwipeToDeleteCallback extends ItemTouchHelper.SimpleCallback {

private Drawable icon;
private ColorDrawable background;
private OnItemSwipeListener onItemSwipeListener;
private boolean swipeEnabled;

private SwipeToDeleteCallback(int dragDirs, int swipeDirs) {
    super(dragDirs, swipeDirs);
}

private SwipeToDeleteCallback(Builder builder) {
    this(builder.dragDirs, builder.swipeDirs);
    background = builder.bgColorSwipe;
    icon = builder.drawableSwipe;
    swipeEnabled = builder.swipeEnabled;
    onItemSwipeListener = builder.onItemSwipeListener;
}

@Override public boolean isItemViewSwipeEnabled() {
    return swipeEnabled;
}

@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    if (viewHolder instanceof AdapterFlightRecords.ViewHolderDate) return 0;
    return super.getSwipeDirs(recyclerView, viewHolder);
}

@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    return false;
}

@Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    int position = viewHolder.getAdapterPosition();
    onItemSwipeListener.onItemSwiped(position);
}

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);

    View itemView = viewHolder.itemView;
    int backgroundCornerOffset = 20; //so background is behind the rounded corners of itemView

    int iconMargin = (itemView.getHeight() - icon.getIntrinsicHeight()) / 2;
    int iconTop = itemView.getTop() + (itemView.getHeight() - icon.getIntrinsicHeight()) / 2;
    int iconBottom = iconTop + icon.getIntrinsicHeight();

    if (dX > 0) { // Swiping to the right
        int iconLeft = itemView.getLeft() + iconMargin;
        int iconRight = itemView.getLeft() + icon.getIntrinsicWidth() + iconMargin;
        icon.setBounds(iconLeft, iconTop, iconRight, iconBottom);

        background.setBounds(itemView.getLeft(), itemView.getTop(),
                itemView.getLeft() + ((int) dX) + backgroundCornerOffset, itemView.getBottom());
    } else if (dX < 0) { // Swiping to the left
        int iconLeft = itemView.getRight() - iconMargin - icon.getIntrinsicWidth();
        int iconRight = itemView.getRight() - iconMargin;
        icon.setBounds(iconLeft, iconTop, iconRight, iconBottom);

        background.setBounds(itemView.getRight() + ((int) dX) - backgroundCornerOffset,
                itemView.getTop(), itemView.getRight(), itemView.getBottom());
    } else { // view is unSwiped
        background.setBounds(0, 0, 0, 0);
    }

    background.draw(c);
    icon.draw(c);
}

public interface OnItemSwipeListener {
    void onItemSwiped(int position);
}

public static final class Builder {
    private int dragDirs, swipeDirs;
    private Drawable drawableSwipe;
    private ColorDrawable bgColorSwipe;
    private OnItemSwipeListener onItemSwipeListener;
    private boolean swipeEnabled;

    public Builder(int dragDirs, int swipeDirs) {
        this.dragDirs = dragDirs;
        this.swipeDirs = swipeDirs;
    }

    public Builder drawableSwipe(Drawable val) {
        drawableSwipe = val;
        return this;
    }

    public Builder bgColorSwipe(ColorDrawable val) {
        bgColorSwipe = val;
        return this;
    }

    public Builder onItemSwipeListener(OnItemSwipeListener val) {
        onItemSwipeListener = val;
        return this;
    }

    public Builder setSwipeEnabled(boolean val) {
        swipeEnabled = val;
        return this;
    }

    public SwipeToDeleteCallback build() {
        return new SwipeToDeleteCallback(this);
    }
}
}