ViewDragHelper实现仿qq列表滑动删除

实现过程概述

实现qq列表侧滑删除,核心还是ViewDragHelper的实现。
关于ViewDragHelper的基础用法,我在另外一篇博客ViewDragHelper简介中已经介绍过了。如果不是特别了解ViewDragHelper,可以看看。
需要实现的ViewGroup是LinearLayout,基本的思路是:LinearLayout中的两个布局都是水平排列。列表的内容布局填充整个列表,菜单布局在屏幕之外,是看不到的。向左滑动内容布局,菜单布局也随之滑动。这时就可以看到屏幕外的菜单布局了。

代码

  1. 自定义控件SwipeLayout
public class SwipeLayout extends LinearLayout {

    private ViewDragHelper viewDragHelper;
    private View contentView;
    private View menuview;
    private int dragDistance;
    private int screenWidth;
    private Context context;

    public SwipeLayout(Context context) {
        this(context, null);


    }

    public SwipeLayout(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context=context;
        init();

    }

    @Override
    protected void onFinishInflate() {
        contentView = getChildAt(0);
        menuview = getChildAt(1);
    }

    void init(){
        viewDragHelper = ViewDragHelper.create(this, new DragHelperCallback());
        /**
         * 获取屏幕宽度
         */
        WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        screenWidth=outMetrics.widthPixels;

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        /**
         * 必须获得menuview的宽度。因为滑动结束后,menuview必须距离右边为dragDistance个像素长度才能显示完全,
         * 这里的距离计算,是以menuview左上角的为起点开始计算的。
         *
         *
         */

        dragDistance = menuview.getMeasuredWidth();
    }



    private class DragHelperCallback extends ViewDragHelper.Callback {
        @Override
        public void onViewDragStateChanged(int state) {
            super.onViewDragStateChanged(state);
            Log.d("liang", "onViewDragStateChanged: "+state);
        }

        @Override
        public boolean tryCaptureView(View view, int i) {
            return view == contentView||view==menuview ;
        }

        @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            /**
             * dx,dy描述的是偏移量
             * 向左边滑动后,contentView随着滑动事件向左边移动。但是menuview是显示不出来的(初始状态menuview是在
             * 屏幕之外的)。
             * 所以要在滑动的同时,给menuview设置偏移量使其跟随contentView滑动并且刷新界面。
             *
             */
            super.onViewPositionChanged( changedView,  left,  top,  dx,  dy);
            if (changedView == contentView) {
                menuview.offsetLeftAndRight(dx);
            } else {
                contentView.offsetLeftAndRight(dx);
            }
            invalidate();
        }

        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
                final int leftBound = getPaddingLeft();
                final int minLeftBound = -leftBound - dragDistance;
                final int newLeft = Math.min(Math.max(minLeftBound, left), 0);//使其不能向右滑动
                Log.d("liang", "clampViewPositionHorizontal: "+newLeft);
                return newLeft;
        }

        @Override
        public int getViewVerticalDragRange(View child) {
            return 0;
        }



        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            /**
             * xvel,yvel表示速度
             */
            super.onViewReleased(releasedChild, xvel, yvel);

            if(contentView.getRight()<(screenWidth-30)){
                viewDragHelper.smoothSlideViewTo(contentView,  -dragDistance, 0);
                ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);

            }else{

                viewDragHelper.smoothSlideViewTo(contentView, 0, 0);
                ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
            }
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if(viewDragHelper.shouldInterceptTouchEvent(ev)) {
            return true;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        viewDragHelper.processTouchEvent(event);
        return true;
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if(viewDragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }
}

注释写得很全,就不一一解释了。需要说明的是:我在这里获取了当前屏幕的宽度,是为了在提高滑动过程中menuView响应事件的灵敏性。

2.listview的item布局文件:

<widget.SwipeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/line"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#FFFDFDFE"
    android:orientation="horizontal">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <ImageView
            android:id="@+id/image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/fkq"
            />

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@+id/image"
            android:layout_alignBottom="@+id/image"
            android:layout_toRightOf="@+id/image"
            android:layout_marginLeft="15dp"
            tools:ignore="RtlHardcoded">

            <TextView
                android:id="@+id/type"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world"
                android:textSize="23sp"
                android:textColor="@color/bright_foreground_material_light"

                />

            <TextView
                android:id="@+id/content"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="How are you?"
                android:textSize="24sp"
                android:textColor="#FF4535FF"
                android:layout_alignParentBottom="true"

                />

            <TextView
                android:id="@+id/time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="yesterday"
                android:textSize="19sp"
                android:textColor="#FF7F7F80"
               android:layout_alignParentRight="true"
                android:padding="10dp"

                />

        </RelativeLayout>

    </RelativeLayout>




    <LinearLayout
        android:layout_width="200dp"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/zhiding"
            android:layout_width="66.5dp"
            android:layout_height="match_parent"
            android:text="置顶"
            android:textColor="#FFF"
            android:textSize="17sp"
            android:gravity="center"
            android:background="#FFC6C6CC"/>
        <TextView
            android:id="@+id/biaojiweiyidu"
            android:layout_width="66.5dp"
            android:layout_height="match_parent"
            android:textColor="#FFF"
            android:textSize="17sp"
            android:text="已读"
            android:gravity="center"
            android:background="#FFFD9C01"/>
        <TextView
            android:id="@+id/delete"
            android:layout_width="66.5dp"
            android:layout_height="match_parent"
            android:textColor="#FFF"
            android:textSize="17sp"
            android:text="删除"
            android:gravity="center"
            android:background="#FFFD3A30"
            android:autoText="false" />

    </LinearLayout>




</widget.SwipeLayout>

这里面包含两个子布局,一个是内容布局,一个是菜单布局。内容布局填充整个item,而菜单布局是在屏幕之外的,不显示。

3.Activity的主布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

   <ListView
       android:id="@+id/listView"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:scrollbars="none">

   </ListView>

</RelativeLayout>

4.listview的适配器及对应的javabean:

public class MyAdapter extends BaseAdapter {
    private Context context;
    private List<Chatter> datas;
    private LayoutInflater inflater;

    public MyAdapter(Context context, List<Chatter> datas) {
        this.context = context;
        this.datas = datas;
        inflater=LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return datas.size();
    }

    @Override
    public Object getItem(int i) {
        return datas.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int position, View covertView, ViewGroup viewGroup) {
        ViewHolder holder=null;
        if(covertView==null){
            holder=new ViewHolder();
            covertView=inflater.inflate(R.layout.item_list,null);
            holder.imageView=(ImageView)covertView.findViewById(R.id.image);
            holder.type=(TextView)covertView.findViewById(R.id.type);
            holder.content=(TextView)covertView.findViewById(R.id.content);
            holder.time=(TextView)covertView.findViewById(R.id.time);
            holder.zhhiding=(TextView)covertView.findViewById(R.id.zhiding);
            holder.biaojiweiyidu=(TextView)covertView.findViewById(R.id.biaojiweiyidu);
            holder.delete=(TextView)covertView.findViewById(R.id.delete);

            covertView.setTag(holder);
        }
        else {
            holder=(ViewHolder)covertView.getTag();
        }

        holder.imageView.setImageBitmap(datas.get(position).getPicture());
        holder.type.setText(datas.get(position).getType());
        holder.content.setText(datas.get(position).getContent());
        holder.time.setText(datas.get(position).getTime());



        holder.biaojiweiyidu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(context, "标记为已读", Toast.LENGTH_SHORT).show();
            }
        });

        holder.delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(context,"已经删除",Toast.LENGTH_SHORT).show();
            }
        });


        holder.zhhiding.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(context, "已经置顶", Toast.LENGTH_SHORT).show();
            }
        });







        return covertView;
    }

    class ViewHolder{
        public ImageView imageView;
        public TextView type,content,time,zhhiding,biaojiweiyidu,delete;

    }
}
public class Chatter {

    private Bitmap picture;
    private String type,content,time;

    public Chatter(Bitmap picture, String type, String content, String time) {
        this.picture = picture;
        this.type = type;
        this.content = content;
        this.time = time;
    }

    public Bitmap getPicture() {
        return picture;
    }

    public void setPicture(Bitmap picture) {
        this.picture = picture;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

5.MainActivity

public class MainActivity extends Activity {
    private LinearLayout linearLayout;
    private TextView textView;

    private ListView listView;
    private List<Chatter> datas;

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

    void initView(){
       listView=(ListView)findViewById(R.id.listView);
        datas=new ArrayList<>();
        Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.fkq);

        Chatter chatter=new Chatter(bitmap,"好友","你好","昨天");
        Chatter chatter1=new Chatter(bitmap,"好友","你在干什么","今天下午");
        Chatter chatter2=new Chatter(bitmap,"朋友","hello","昨天");
        Chatter chatter3=new Chatter(bitmap,"亲人","病好了吗","前天");
        Chatter chatter4=new Chatter(bitmap,"老师","作业做完了吗","昨天");
        Chatter chatter5=new Chatter(bitmap,"老师","今天不上课","今天");
        Chatter chatter6=new Chatter(bitmap,"同学","去打球","子阿武");
        Chatter chatter7=new Chatter(bitmap,"同学","去打球","子阿武");
        Chatter chatter8=new Chatter(bitmap,"同学","去打球","子阿武");

        datas.add(chatter);
        datas.add(chatter1);
        datas.add(chatter2);
        datas.add(chatter3);
        datas.add(chatter4);
        datas.add(chatter5);
        datas.add(chatter6);
        datas.add(chatter7);
        datas.add(chatter8);

        MyAdapter adapter=new MyAdapter(this,datas);
        listView.setAdapter(adapter);



    }

}

效果图

这里写图片描述
这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值