Android 实现QQ侧滑删除效果

2020-06-21  本文已影响0人  因为我的心

一、前言:

分析: Android中什么组件自带了水平滑动? 我首当其冲就想到HorizontalScrollView。既然是简单实现,那我们何方不继承一下HorizontalScrollView呢?

接下来我们将HorizontalScrollView分成ItemView + 抽屉部分。

我们只需要监听用户的滑动事件,当用户滑动超过指定距离时,就移动HorizontalScrollView,将隐藏的“抽屉部分”显示出来,当用户做相反的滑动时,隐藏“抽屉部分”即可。

gitee地址:https://gitee.com/luoyanyong/SlidingDeleteDemo

效果图:


图片.png

二、实现:

1、依赖:

  //recyclerview使用
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
//  implementation 'com.android.support:recyclerview-v7:29.0.0'
    //BRVAH使用
    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.47'
    //万能插件
    implementation 'com.blankj:utilcodex:1.25.2'

2、 自定义SlidingDeleteView

/**
 * 滑动删除widget
 *
 * @author Junhui
 */

public class SlidingDeleteView extends HorizontalScrollView {
    private static final String TAG = "SlidingDeleteView";

    /**
     * 抽屉视图(注意:recyclerview/listview中不能使用button,button会抢夺焦点) - 父件
     */
    private LinearLayout slidingParent;
    /**
     * 是否开启滑动抽屉
     */
    public boolean isEnable = true;
    /**
     * 抽屉视图是否可见
     */
    public boolean deleteViewVisibile = false;

    private boolean isFirst = true;
    //监听器
    private OnDeleteViewStateChangedListener onStateChangedListener;

    /**
     * 抽屉视图状态变化回调接口
     */
    public interface OnDeleteViewStateChangedListener {
        void onVisibile();

        void onGone();

        void onDownOrMove();
    }

    public SlidingDeleteView(Context context) {
        this(context, null);
    }

    public SlidingDeleteView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SlidingDeleteView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (isFirst) {
            init();
            isFirst = false;
        }
    }

    private void init() {
        slidingParent = (LinearLayout) findViewById(R.id.lay_sliding);
    }

    public void setOnDeleteViewStateChangedListener(OnDeleteViewStateChangedListener onStateChangedListener) {
        this.onStateChangedListener = onStateChangedListener;
    }

    public boolean isEnable() {
        return isEnable;
    }

    public void setEnable(boolean enable) {
        isEnable = enable;
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action) {
            case MotionEvent.ACTION_MOVE:
                if (!isEnable) {
                    return false;
                }
            case MotionEvent.ACTION_DOWN:
                if (onStateChangedListener != null) {
                    onStateChangedListener.onDownOrMove();
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                measureScrollX();
                return true;
            default:
                break;
        }
        return super.onTouchEvent(ev);
    }

    /**
     * 计算X轴滑动距离,并做出相应操作
     */
    private void measureScrollX() {
        if (getScrollX() < slidingParent.getWidth() / 3) {
            //TODO 当滑动距离小于 抽屉视图宽度 * 1/3 时,隐藏删除视图
            setDeleteViewGone();
        } else {
            setDeleteViewVisibile();
        }
    }

    /**
     * 隐藏滑动布局
     */
    public void setDeleteViewGone() {
        deleteViewVisibile = false;
        this.smoothScrollTo(0, 0);
        if (onStateChangedListener != null) {
            onStateChangedListener.onGone();
        }
    }
    /**
     * 显示滑动布局
     */
    public void setDeleteViewVisibile() {
        Log.d(TAG, "抽屉的固定宽度为 == " + slidingParent.getWidth());
        deleteViewVisibile = true;
        this.smoothScrollTo(slidingParent.getWidth(), 0);

        if (onStateChangedListener != null) {
            onStateChangedListener.onVisibile();
        }
    }

}

2、 MainActivity

public class MainActivity extends AppCompatActivity {

    RecyclerView rv_list;
    private List<LoginBean>  list = new ArrayList<>();
    private  MyListAdapter myListAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rv_list = (RecyclerView) findViewById(R.id.rv_list);
        init();
    }
    /**
     * 初始化数据
     */
    private void init() {

        try {
            for (int i=1;i<21;i++){
                list.add(new LoginBean("第"+i+"条数据"));
            }
            if (myListAdapter==null){
                rv_list.setLayoutManager(new LinearLayoutManager(this));
                rv_list.addItemDecoration(new DividerItemDecoration(this, LinearLayout.VERTICAL));
                myListAdapter = new MyListAdapter(R.layout.sample_slidingview,list);
                rv_list.setAdapter(myListAdapter);
            }else {
                myListAdapter.notifyDataSetChanged();
            }

            myListAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
                @Override
                public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                    switch (view.getId()){
                        case R.id.tv_delete:
                            list.remove(position);
                            myListAdapter.notifyDataSetChanged();
                            Log.d("LUO","===删除==");
                            break;
                        case R.id.tv_cancel:
                           // SlidingDeleteView  slidingDeleteView = (SlidingDeleteView) adapter.getViewByPosition(rv_list, position, R.id.slidingview);
                            //slidingDeleteView.setDeleteViewGone();
                           // myListAdapter.notifyItemChanged(position);
                            myListAdapter.notifyDataSetChanged();
                            Log.d("LUO","===隐藏==");
                            break;
                        default:
                            break;
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3、MyListAdapter 类

public class MyListAdapter extends BaseQuickAdapter<LoginBean, BaseViewHolder> {
    public MyListAdapter(int layoutResId, List<LoginBean> data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, LoginBean item) {
        //TODO 这里需要重新计算 item - containerView的宽度,否则containerView会显示错误(重要)
        LinearLayout containerView = helper.getView(R.id.lay_container);
        final SlidingDeleteView slidingDeleteView = helper.getView(R.id.slidingview);
        TextView tv_key = helper.getView(R.id.tv_key);
        TextView tv_cancel = helper.getView(R.id.tv_cancel);
        TextView tv_delete = helper.getView(R.id.tv_delete);

        containerView.getLayoutParams().width = ScreenUtils.getScreenWidth();
        slidingDeleteView.setEnable(true);
        //默认隐藏
        slidingDeleteView.setDeleteViewGone();

        tv_key.setText(item.getName());
        slidingDeleteView.setOnDeleteViewStateChangedListener(new SlidingDeleteView.OnDeleteViewStateChangedListener() {
            @Override
            public void onVisibile() {
                Log.d("LUO", "显示抽屉视图");
            }

            @Override
            public void onGone() {
                Log.d("LUO", "隐藏抽屉视图");
            }

            @Override
            public void onDownOrMove() {

            }
        });
        
        //添加点击事件
        helper.addOnClickListener(R.id.tv_key);
        helper.addOnClickListener(R.id.tv_cancel);
        helper.addOnClickListener(R.id.tv_delete);

    }
}
上一篇下一篇

猜你喜欢

热点阅读