自定义控件--滑动删除

来源:互联网 发布:淘宝买iphone8靠谱吗 编辑:程序博客网 时间:2024/06/05 07:38
1.应用场景:替换item长按删除
2.实现逻辑:
a.自定义一个可以滑动的布局;

b.将该布局放入adapter的布局中,需要处理滑动冲突;

3.目录结构:


4.java代码:

4.1 SwipeLayoutManager.java

package com.weizh.swipedelete.manager;import com.weizh.swipedelete.widget.SwipeLayout;/** * Created by weizh_000 on 2016/8/24. */public class SwipeLayoutManager {    private static SwipeLayoutManager swipeLayoutManager = new SwipeLayoutManager();    private SwipeLayout currentLayout;    public static SwipeLayoutManager getInstance(){        return swipeLayoutManager;    }    //记录当前打开的是哪一个swipeLayout    public void setCurrentLayout(SwipeLayout swipeLayout){        this.currentLayout = swipeLayout;    }    //清除记录    public void clearCurrentLayout(){        currentLayout=null;    }    //关闭记录中的swipelayout    public void closeSwipeLayout(){        if (currentLayout!=null){            currentLayout.close();        }    }    //判断是否可以左右滑动swipelayout    public boolean isShouldOpen(SwipeLayout swipeLayout){        if (currentLayout==null){            //说明无记录,可以打开            return true;        }else {            //说明有记录,            //记录的是自己,可以左右滑动            //记录的是别的swipelayout,则不能滑动            return currentLayout==swipeLayout;        }    }    public void resumeSwipeLayout() {        if(currentLayout!=null){            currentLayout.resume();        }    }}

4.2 SwipeLayout.java

package com.weizh.swipedelete.widget;import android.content.Context;import android.support.v4.view.ViewCompat;import android.support.v4.widget.ViewDragHelper;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.FrameLayout;import com.weizh.swipedelete.manager.SwipeLayoutManager;/** * Created by weizh_000 on 2016/8/23. */public class SwipeLayout extends FrameLayout {    private View contentView;//item内容区域的view    private View deleteView;//delete区域的view    private int contentWidth;//内容区域的宽度    private int deleteWidth;//delete区域的宽度    private int deleteHeight;//delete区域的高度    private ViewDragHelper dragHelper;    private float downX;    private float downY;    private SwipeState currentState;//当前状态是默认是关闭状态    public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    public SwipeLayout(Context context) {        super(context);        init();    }    public SwipeLayout(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    private void init() {        dragHelper = ViewDragHelper.create(this, callback);        currentState = SwipeState.Close;    }    enum SwipeState {        Open, Close;    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        contentView = getChildAt(0);        deleteView = getChildAt(1);    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        contentWidth = contentView.getMeasuredWidth();        deleteWidth = deleteView.getMeasuredWidth();        deleteHeight = deleteView.getMeasuredHeight();    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        contentView.layout(0, 0, contentWidth, deleteHeight);        deleteView.layout(contentView.getRight(), 0, contentView.getRight() + deleteWidth, deleteHeight);    }    private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {        @Override        public boolean tryCaptureView(View child, int pointerId) {            return child == contentView || child == deleteView;        }        @Override        public int getViewHorizontalDragRange(View child) {            return deleteWidth;        }        @Override        public int clampViewPositionHorizontal(View child, int left, int dx) {            if (child == contentView) {                if (left < -deleteWidth) left = -deleteWidth;                if (left > 0) left = 0;            } else if (child == deleteView) {                if (left < contentWidth - deleteWidth) left = contentWidth - deleteWidth;                if (left > contentWidth) left = contentWidth;            }            return left;        }        @Override        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {//            super.onViewPositionChanged(changedView, left, top, dx, dy);            //做伴随移动            if (changedView == contentView) {                deleteView.layout(deleteView.getLeft() + dx, 0, deleteView.getRight() + dx, deleteHeight);            } else if (changedView == deleteView) {                contentView.layout(contentView.getLeft() + dx, 0, contentView.getRight() + dx, deleteHeight);            }            //判断开关逻辑            if (contentView.getLeft() == 0) {                //说明state应更改为关闭                currentState = SwipeState.Close;                //清空已打开swipelayout记录                SwipeLayoutManager.getInstance().clearCurrentLayout();            } else if (contentView.getLeft() == -deleteWidth) {                //说明state应更改为打开                currentState = SwipeState.Open;                //记录已打开swipelayout                SwipeLayoutManager.getInstance().setCurrentLayout(SwipeLayout.this);            }        }        @Override        public void onViewReleased(View releasedChild, float xvel, float yvel) {            super.onViewReleased(releasedChild, xvel, yvel);            if (contentView.getLeft() < -deleteWidth / 2) {                //应该打开                open();            } else {                //应该关闭                close();            }        }    };    //打开swipelayout    private void open() {        dragHelper.smoothSlideViewTo(contentView, -deleteWidth, 0);        ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);    }    //关闭swipelayout    public void close() {        dragHelper.smoothSlideViewTo(contentView, 0, 0);        ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);    }//恢复swipelayout至初始位置    public void resume() {        contentView.layout(0,0,contentWidth,deleteHeight);        deleteView.layout(contentView.getRight(),0,contentView.getRight()+deleteWidth,deleteHeight);    }    @Override    public void computeScroll() {        if (dragHelper.continueSettling(true)) {            ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);        }    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        //让dragHelper决定是否拦截事件        boolean b = dragHelper.shouldInterceptTouchEvent(ev);        if (!SwipeLayoutManager.getInstance().isShouldOpen(this)) {            b = true;//将事件传递给onTouchEvent            //当前swipelayout不能滑动,先关闭swipelayout            SwipeLayoutManager.getInstance().closeSwipeLayout();            //请求父类不要拦截事件            requestDisallowInterceptTouchEvent(true);        }        return b;    }    @Override    public boolean onTouchEvent(MotionEvent event) {        //如果有已打开的swipelayout,则先关闭        if (!SwipeLayoutManager.getInstance().isShouldOpen(this)) {            //消费掉触摸事件            return true;        }        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                downX = event.getX();                downY = event.getY();                break;            case MotionEvent.ACTION_MOVE:                float moveX = event.getX();                float moveY = event.getY();                float delatX = moveX - downX;                float delatY = moveY - downY;                if (Math.abs(delatX) > Math.abs(delatY)) {                    //禁止listview拦截事件                    requestDisallowInterceptTouchEvent(true);                }                downX = moveX;                downY = moveY;                break;            case MotionEvent.ACTION_UP:                break;        }        //交给dragHelper处理触摸事件        dragHelper.processTouchEvent(event);        return true;    }}

4.3 MainActivity.java

package com.weizh.swipedelete;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.AbsListView;import android.widget.BaseAdapter;import android.widget.ListView;import android.widget.TextView;import com.weizh.swipedelete.manager.SwipeLayoutManager;import java.util.ArrayList;public class MainActivity extends AppCompatActivity {    private ListView lvListView;    private ArrayList<String> strings;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        initData();    }    private void initData() {        //1.设置数据        strings = new ArrayList<>();        for (int i=0;i<30;i++) {            strings.add("name - "+i);        }        lvListView.setAdapter(new MyAdapter());        lvListView.setOnScrollListener(new AbsListView.OnScrollListener() {            @Override            public void onScrollStateChanged(AbsListView absListView, int scrollState) {                if(scrollState==SCROLL_STATE_TOUCH_SCROLL){                    //垂直滑动则需要关闭已经打开的swipelayout                    SwipeLayoutManager.getInstance().closeSwipeLayout();                }            }            @Override            public void onScroll(AbsListView absListView, int i, int i1, int i2) {            }        });    }    private void initView() {         lvListView=(ListView) findViewById(R.id.lv_list);    }    class MyAdapter extends BaseAdapter{        @Override        public int getCount() {            return strings.size();        }        @Override        public Object getItem(int i) {            return null;        }        @Override        public long getItemId(int i) {            return 0;        }        @Override        public View getView(final int position, View convertView, ViewGroup viewGroup) {            ViewHolder holder=null;            if (convertView==null){                convertView=View.inflate(getApplicationContext(),R.layout.list_item,null);                holder=new ViewHolder();                holder.tvName= (TextView) convertView.findViewById(R.id.tv_name);                holder.tvDelete= (TextView) convertView.findViewById(R.id.tv_delete);                convertView.setTag(holder);            }else {                holder= (ViewHolder) convertView.getTag();            }            holder.tvName.setText(strings.get(position));            //给delete textview设置点击事件            holder.tvDelete.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View view) {                    //恢复swipelayout至初始位置                    SwipeLayoutManager.getInstance().resumeSwipeLayout();                    //清除swipelayout打开记录                    SwipeLayoutManager.getInstance().clearCurrentLayout();                    strings.remove(position);//从集合中移除对应的条目数据                    notifyDataSetChanged();//通知数据更新                }            });            return convertView;        }    }    class ViewHolder{        public TextView tvName;        public TextView tvDelete;    }}

5. 布局文件

5.1 activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout 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:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.weizh.swipedelete.MainActivity">    <ListView        android:layout_width="match_parent"        android:layout_height="match_parent"        android:id="@+id/lv_list"        ></ListView></LinearLayout>

5.2 layout_content.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="80dp"    android:paddingLeft="15dp"    android:background="#33666666"    android:gravity="center_vertical"    android:orientation="horizontal" >        <ImageView android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:background="@drawable/head_1"/>        <TextView android:layout_width="match_parent"        android:layout_height="wrap_content"        android:textColor="#99000000"        android:id="@+id/tv_name"        android:layout_marginLeft="10dp"        android:textSize="20sp"        android:text="名称"/></LinearLayout>

5.3 layout_delete.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="wrap_content"    android:layout_height="80dp"    android:orientation="horizontal" >    <TextView android:layout_width="100dp"        android:layout_height="match_parent"        android:textSize="18sp"        android:textColor="#ffffff"        android:gravity="center"        android:background="#aa000000"        android:text="Call"/>        <TextView android:layout_width="100dp"        android:layout_height="match_parent"        android:textSize="18sp"        android:textColor="#ffffff"        android:id="@+id/tv_delete"        android:gravity="center"        android:background="#eeff0000"        android:text="Delete"/></LinearLayout>

5.4 list_item.xml

<?xml version="1.0" encoding="utf-8"?><com.weizh.swipedelete.widget.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/sd_delete"    android:layout_width="match_parent"    android:layout_height="wrap_content">        <include layout="@layout/layout_content" />        <include layout="@layout/layout_delete" /></com.weizh.swipedelete.widget.SwipeLayout>

6.运行效果图:


7.源码地址:https://github.com/Jszgw/SwipeDelete

0 0