RecyclerView 滑动删除仍然显示不完整滑动的可绘制

Posted

技术标签:

【中文标题】RecyclerView 滑动删除仍然显示不完整滑动的可绘制【英文标题】:RecyclerView swipe to delete still shows drawable with uncomplete swipe 【发布时间】:2019-09-04 10:36:38 【问题描述】:

我的 RecyclerView 使用 ItemTouchHelper 启用向右滑动功能,如下所示

ItemTouchHelper itemTouchHelper = new ItemTouchHelper(createHelperCallback());
itemTouchHelper.attachToRecyclerView(myRecyclerView);

private ItemTouchHelper.Callback createHelperCallback() 
    return new ItemDragSwipeCallback(this, R.color.swipe_delete, R.drawable.ic_delete_black_24dp,
            0, ItemTouchHelper.RIGHT, new ItemDragSwipeCallback.OnTouchListener() 
        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) 
            return false;
        

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) 
            // delete code
        
    );

自定义ItemTouchHelper.SimpleCallback

public class ItemDragSwipeCallback extends ItemTouchHelper.SimpleCallback 


    private Drawable mIcon;
    private final ColorDrawable mBackground;

    public interface OnTouchListener 
        boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target);

        void onSwiped(RecyclerView.ViewHolder viewHolder, int direction);
    

    private OnTouchListener mOnTouchListener;

    public ItemDragSwipeCallback(Context context, int backgroundColor, int drawable, int dragDirs, int swipeDirs, OnTouchListener onTouchListener) 
        super(dragDirs, swipeDirs);
        mOnTouchListener = onTouchListener;
        mIcon = ContextCompat.getDrawable(context, drawable);
        mBackground = new ColorDrawable(context.getResources().getColor(backgroundColor));
    

    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) 
        return mOnTouchListener.onMove(recyclerView, viewHolder, target);
    

    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) 
        mOnTouchListener.onSwiped(viewHolder, direction);
    

    @Override
    public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull 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 = 25; //so mBackground is behind the rounded corners of itemView

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

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

            mBackground.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 - mIcon.getIntrinsicWidth();
            int iconRight = itemView.getRight() - iconMargin;
            mIcon.setBounds(iconLeft, iconTop, iconRight, iconBottom);

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

        mBackground.draw(c);
        mIcon.draw(c);
    

布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_
        android:layout_
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

我的问题是,当我假装滑动以删除项目并改变主意时,可绘制的删除图标不会隐藏,直到我触摸屏幕进行任何其他操作。

更新:我通过将 list_item 的背景颜色更改为某种颜色找到了解决方案。但如果我需要透明背景,这不是正确的解决方案。

【问题讨论】:

我认为您应该在else // view is unSwiped mBackground.setBounds(0, 0, 0, 0); 中将图标的边界改回0。只需添加mIcon.setBounds(0,0,0,0); 【参考方案1】:

修改了自定义 ItemTouchHelper.SimpleCallback 的 onChildDraw() 方法,使用mIcon.setBounds(0, 0, 0, 0);取消滑动时将图标的边界设置为 0

public class ItemDragSwipeCallback extends ItemTouchHelper.SimpleCallback 


    private Drawable mIcon;
    private final ColorDrawable mBackground;

    public interface OnTouchListener 
        boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target);

        void onSwiped(RecyclerView.ViewHolder viewHolder, int direction);
    

    private OnTouchListener mOnTouchListener;

    public ItemDragSwipeCallback(Context context, int backgroundColor, int drawable, int dragDirs, int swipeDirs, OnTouchListener onTouchListener) 
        super(dragDirs, swipeDirs);
        mOnTouchListener = onTouchListener;
        mIcon = ContextCompat.getDrawable(context, drawable);
        mBackground = new ColorDrawable(context.getResources().getColor(backgroundColor));
    

    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) 
        return mOnTouchListener.onMove(recyclerView, viewHolder, target);
    

    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) 
        mOnTouchListener.onSwiped(viewHolder, direction);
    

    @Override
    public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull 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 = 25; //so mBackground is behind the rounded corners of itemView

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

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

            mBackground.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 - mIcon.getIntrinsicWidth();
            int iconRight = itemView.getRight() - iconMargin;
            mIcon.setBounds(iconLeft, iconTop, iconRight, iconBottom);

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

        mBackground.draw(c);
        mIcon.draw(c);
    

【讨论】:

以上是关于RecyclerView 滑动删除仍然显示不完整滑动的可绘制的主要内容,如果未能解决你的问题,请参考以下文章

android recyclerview滑动监听滑过多少条

Android——实现RecyclerView左侧滑删除与右侧滑选择

Android 使用HorizontalScrollView实现RecyclerView左滑删除的功能

Android 使用HorizontalScrollView实现RecyclerView左滑删除的功能

如何从“滑动滑块同步”中删除滑块导航并显示缩略图?

如何在 RecyclerView 上滑动删除?