Android简单实现滑动删除Item

需求:如题,要做出类似QQ左滑删除的效果。

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

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

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


GitHub下载地址:https://github.com/yanjunhui2014/SlidingDeleteView


需求分析已定,先给大家看效果。

Android简单实现滑动删除Item_第1张图片


各位看官是不是急不可耐的想看代码了,这就上:

package com.sliding.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

import com.sliding.R;

/**
 * 滑动删除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();
        }
    }

}

以下是Activity中的代码,需要注意的是,需要在adapter-bindview时指定ItemView的宽度,否则会显示异常。

package com.sliding;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.sliding.utils.ScreenUtils;
import com.sliding.widget.SlidingDeleteView;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    RecyclerView recyclerView;
    MyAdapter myAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();
    }

    private void init() {
        recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        myAdapter = new MyAdapter();
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayout.VERTICAL));
        recyclerView.setAdapter(myAdapter);
    }

    class MyAdapter extends RecyclerView.Adapter {

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemView = LayoutInflater.from(getBaseContext()).inflate(R.layout.sample_slidingview, parent, false);
            return new MyViewHolder(itemView);
        }

        @Override
        public void onBindViewHolder(MyViewHolder holder, final int position) {
            //TODO 这里需要重新计算 item - containerView的宽度,否则containerView会显示错误(重要)
            LinearLayout containerView = (LinearLayout) holder.slidingDeleteView.findViewById(R.id.lay_container);
            containerView.getLayoutParams().width = ScreenUtils.getScreenWidth(getBaseContext());
            holder.slidingDeleteView.setEnable(true);
            holder.slidingDeleteView.setOnDeleteViewStateChangedListener(new SlidingDeleteView.OnDeleteViewStateChangedListener() {
                @Override
                public void onVisibile() {
                    Log.i(TAG, "显示抽屉视图");
                }

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

                @Override
                public void onDownOrMove() {

                }
            });

            holder.tvKey.setText("key");
            holder.tvValue.setText("" + position);
            holder.tvDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(getBaseContext(), "position == " + position + " onClick", Toast.LENGTH_LONG).show();
                }
            });
        }

        @Override
        public int getItemCount() {
            return 20;
        }

    }

    class MyViewHolder extends RecyclerView.ViewHolder {

        SlidingDeleteView slidingDeleteView;
        TextView tvKey;
        TextView tvValue;
        TextView tvDelete;

        public MyViewHolder(View itemView) {
            super(itemView);
            slidingDeleteView = (SlidingDeleteView) itemView.findViewById(R.id.slidingview);
            tvKey = (TextView) itemView.findViewById(R.id.tv_key);
            tvValue = (TextView) itemView.findViewById(R.id.tv_value);
            tvDelete = (TextView) itemView.findViewById(R.id.tv_delete);
        }

    }


}

至于剩下的layout、values、drawable等文件就不一一上传了,有需要的直接去本人的github博客下载即可。

github下载地址:https://github.com/yanjunhui2014/SlidingDeleteView



你可能感兴趣的:(个人)