高仿QQ侧滑item删除的自定义ListView

来源:互联网 发布:coc王升级数据2016 编辑:程序博客网 时间:2024/06/09 14:28

预览效果GIF图:



带注释源码:

注释中已将实现步骤写好,欢迎留言交流,运行Mode地址:https://github.com/jiarWang/AndroidView/tree/master/SlideListView_4_28

public class SlideListView extends ListView {    private final int CONTENT_POSITION = 0;    private final int DELETE_POSITION = 1;        private int mScreenWidth;   //屏幕宽度    private int deleteWidth;    private ViewGroup targetItemViewGroup;  //被标记item    private boolean isSelect;   //是否有选中,标记    private int downX;  //DOWN时的X    private int downY;    private LinearLayout.LayoutParams childOneParams;   //padding操作的child数据    public SlideListView(Context context) {        super(context, null);        init(context);    }    public SlideListView(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }    public SlideListView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context);    }    public SlideListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);        init(context);    }    private void init(Context context) {        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics displayMetrics = new DisplayMetrics();        wm.getDefaultDisplay().getMetrics(displayMetrics);        mScreenWidth = displayMetrics.widthPixels;    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        switch (ev.getAction()){            case MotionEvent.ACTION_DOWN:                return performActionAsDown(ev);            case MotionEvent.ACTION_MOVE:                performActionAsMove(ev);                break;            case MotionEvent.ACTION_UP:                performActionAsUp(ev);                break;        }        return super.onTouchEvent(ev);    }/** * 1、获取屏幕宽度,绘制当前的子item,使其保持DOWN前的状态 * 2、判断是否有item已经被选中标记(有Delete控件); *          如果已经有被标记item,判断被标记item是否为当前点击处对应的item? *              是:则此时不做处理, *              否:则还原被标记item,拦截事件 *          如果没有,则将当前DOWN处的作为标记item * */    private boolean performActionAsDown(MotionEvent ev) {                downX = (int)ev.getX();        downY = (int)ev.getY();                ViewGroup tmpItem = (ViewGroup) this.getChildAt(pointToPosition(downX, downY) - getFirstVisiblePosition());        if (isSelect){            if (tmpItem != targetItemViewGroup){                turnToNormal();                return false;            }        }else{            targetItemViewGroup = tmpItem;            childOneParams = (LinearLayout.LayoutParams) targetItemViewGroup.getChildAt(CONTENT_POSITION).getLayoutParams();            childOneParams.width = mScreenWidth;            targetItemViewGroup.getChildAt(CONTENT_POSITION).setLayoutParams(childOneParams);            deleteWidth = targetItemViewGroup.getChildAt(DELETE_POSITION).getLayoutParams().width;        }        return true;    }/** * 重置选中item视图,标记判断置位false,选中item置为null * */    public void turnToNormal() {        if (targetItemViewGroup != null){            childOneParams.leftMargin = 0;            targetItemViewGroup.getChildAt(CONTENT_POSITION).setLayoutParams(childOneParams);            isSelect = false;        }    }    /**通过performActionAsDown后,只有被标记item才有MOVE响应 * 判断是否有item已经被选中标记(有Delete控件); *          是:判断手势-->向左不处理,向右则修改Child的padding,不得超过padding界线 *          否:判断手势-->向右不处理,向左则修改Child的padding,不得超过padding界线 * */    private void performActionAsMove(MotionEvent ev) {        if (targetItemViewGroup == null) return;        int moveX = (int) ev.getX();        int moveY = (int)ev.getY();                int diffX = moveX - downX;        int diffY = moveY - downY;                if (isSelect){            if (diffX > 0  && Math.abs(diffX) > Math.abs(diffY)){   //右滑                if (diffX > deleteWidth){                    diffX = deleteWidth;                }                childOneParams.leftMargin = diffX - deleteWidth;            }        }else {            if (diffX < 0 && Math.abs(diffX) > Math.abs(diffY)){                if (Math.abs(diffX) > deleteWidth){                    diffX = -deleteWidth;                }                childOneParams.leftMargin = diffX;            }        }        targetItemViewGroup.getChildAt(CONTENT_POSITION).setLayoutParams(childOneParams);    }/** * 判断是否有选中标记位? *      有:标记item的Delete控件全显示,设置标志位 *      无:则标记item至为normal,设置标志位 * */    private void performActionAsUp(MotionEvent ev) {        int upX = (int) ev.getX();        int upY = (int)ev.getY();        int diffX = upX - downX;        int diffY = upY - downY;        if (! isSelect && diffX < 0 && Math.abs(diffX) > Math.abs(diffY)){            isSelect = true;            childOneParams.leftMargin = - deleteWidth;        }else if (isSelect && diffX > 0 && Math.abs(diffX) > Math.abs(diffY)){            childOneParams.leftMargin = 0;            isSelect = false;        }        targetItemViewGroup.getChildAt(CONTENT_POSITION).setLayoutParams(childOneParams);    }}

自定义SlideAdapter源码:

adapter源码比较简单,只是需要说明的是,要将SlideListView对象传递进来,在执行删除操作时需要。

public class SlideAdapter extends BaseAdapter {    private List<String> list = new ArrayList<>();    private LayoutInflater inflater;    private SlideListView listView;    SlideAdapter(Context context, List<String> data, SlideListView listView){        list.clear();        list.addAll(data);        inflater = LayoutInflater.from(context);        this.listView = listView;    }    @Override    public int getCount() {        return list.size();    }    @Override    public Object getItem(int position) {        return list.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(final int position, View convertView, ViewGroup parent) {        Holder holder = null;        if (convertView == null) {            convertView = inflater.inflate(R.layout.slide_item, parent, false);            holder = new Holder();            holder.tv_content = (TextView) convertView.findViewById(R.id.tv_content);            holder.tv_delete = (TextView) convertView.findViewById(R.id.tv_delete);            convertView.setTag(holder);        }else {            holder = (Holder) convertView.getTag();        }        holder.tv_content.setText(getItem(position).toString());        holder.tv_delete.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                list.remove(position);                listView.turnToNormal();                notifyDataSetChanged();            }        });        return convertView;    }    class Holder{        TextView tv_content;        TextView tv_delete;    }}

实例化及适配器的使用:

slideListView = (SlideListView) findViewById(R.id.slideView);
slideAdapter = new SlideAdapter(this, data, slideListView);slideListView.setAdapter(slideAdapter);


0 0
原创粉丝点击