Android开发之高仿QQ消息侧拉删除

Android开发之高仿QQ消息侧拉删除

QQ消息的侧滑删除效果之炫酷,想必大家都见过吧,本人作为一名安卓开发人员,遇到如此炫酷的效果,怎能不研究一番呢,现本人已实现其基本功能,现将代码贴出,望各位大神批评指正,不喜勿喷,灰常感谢O(∩_∩)O哈哈~

下面我们废话少说,直接上代码啦!
核心代码:
MainActivity
package com.hxht.testlvwithdragmessageitem;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

import com.hxht.testlvwithdragmessageitem.adapter.MyAdapter;
import com.hxht.testlvwithdragmessageitem.customview.DragMessageView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity {

    private ListView lv;
    private String[] names = new String[]{
            "宋江",
            "卢俊义",
            "吴用",
            "公孙胜",
            "关胜",
            "林冲",
            "秦明",
            "呼延灼",
            "花荣",
            "柴进",
            "李应",
            "朱仝",
            "鲁智深",
            "武松",
            "董平",
            "张清",
            "杨志",
            "徐宁",
            "索超",
            "戴宗",
            "刘唐",
            "李逵",
            "史进",
            "穆弘",
            "雷横",
            "李俊",
            "阮小二",
            "张横",
            "阮小五",
            "张顺",
            "阮小七",
            "杨雄",
            "石秀",
            "解珍",
            "解宝 ",
            "燕青",
            "朱武",
            "黄信",
            "孙立",
            "宣赞",
            "郝思文",
            "韩滔",
            "彭玘",
            "单廷圭",
            "魏定国",
            "萧让",
            "裴宣",
            "欧鹏",
            "邓飞",
            "燕顺",
            "杨林",
            "凌振",
            "蒋敬",
            "吕方",
            "郭盛",
            "安道全",
            "皇甫端",
            "王英",
            "扈三娘",
            "鲍旭",
            "樊瑞",
            "孔明",
            "孔亮",
            "项充",
            "李衮",
            "金大坚",
            "马麟",
            "童威",
            "童猛",
            "孟康",
            "侯健",
            "陈达",
            "杨春",
            "郑天寿",
            "陶宗旺",
            "宋清",
            "乐和",
            "龚旺",
            "丁得孙",
            "穆春",
            "曹正",
            "宋万",
            "杜迁",
            "薛永",
            "李忠",
            "周通",
            "汤隆",
            "杜兴",
            "邹渊",
            "邹润",
            "朱贵",
            "朱富",
            "施恩",
            "蔡福",
            "蔡庆",
            "李立",
            "李云",
            "焦挺",
            "石勇",
            "孙新",
            "顾大嫂",
            "孙二娘",
            "王定六",
            "郁保四",
            "白胜",
            "时迁",
            "段景住"
    };
    private List<String> list;

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

        initView();

        initData();
    }

    private void initView() {
        lv = (ListView) findViewById(R.id.lv);
        list = new ArrayList<>();
        list.clear();
        for (int i = 0; i < names.length; i++) {
            list.add(names[i]);
        }
    }

    private void initData() {
        MyAdapter adapter = new MyAdapter(list, MainActivity.this);
        lv.setAdapter(adapter);
    }
}

Utils:
package com.hxht.testlvwithdragmessageitem.utils;


import android.app.Activity;
import android.widget.Toast;

public class Utils {
    public static void showSafeToast(final Activity activity, final String msg) {

        if ("main".equals(Thread.currentThread().getName())) {
            Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show();
        } else {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
}

DragMessageView:
package com.hxht.testlvwithdragmessageitem.customview;

import android.content.Context;
import android.graphics.Rect;
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.view.ViewGroup;
import android.widget.FrameLayout;

public class DragMessageView extends FrameLayout {

    private ViewDragHelper mViewDragHelper;
    private ViewGroup backView;
    private ViewGroup frontView;
    private int mWidth;
    private int mHeight;
    private int mRange;

    private static enum Status {
        CLOSE,
        OPEN,
        DRAGING
    }

    public interface OnDragChangeListener {
        void onOpen();

        void onClose();

        void onDraging();
    }

    private OnDragChangeListener mOnDragChangeListener;

    public OnDragChangeListener getmOnDragChangeListener() {
        return mOnDragChangeListener;
    }

    public void setmOnDragChangeListener(OnDragChangeListener mOnDragChangeListener) {
        this.mOnDragChangeListener = mOnDragChangeListener;
    }

    private Status status = Status.CLOSE;

    private ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() {

        //第三步:处理监听
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            return true;
        }

        @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            super.onViewPositionChanged(changedView, left, top, dx, dy);

            if (changedView == frontView) {
                backView.offsetLeftAndRight(dx);
            } else if (changedView == backView) {
                frontView.offsetLeftAndRight(dx);
            }

            dispatchDragEvents();

            invalidate();
        }

        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);

            if (xvel < 0) {
                open();
            } else if (xvel == 0 && frontView.getLeft() < -(mRange / 2)) {
                open();
            } else {
                close();
            }
        }

        @Override
        public int getViewHorizontalDragRange(View child) {
            return mRange;
        }

        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {

            if (child == frontView) {
                left = fixLeft(left);
            }

            if (child == backView) {
                left = computeLeft(left);
            }

            return left;
        }
    };

    private void dispatchDragEvents() {

        Status lastStatus = status;
        status = updateStatus();

        if (lastStatus != status) {
            if (mOnDragChangeListener != null) {
                if (status == Status.CLOSE) {
                    mOnDragChangeListener.onClose();
                } else if (status == Status.OPEN) {
                    mOnDragChangeListener.onOpen();
                } else {
                    mOnDragChangeListener.onDraging();
                }
            }
        }
    }

    private Status updateStatus() {
        int left = frontView.getLeft();
        if (left == 0) {
            return Status.CLOSE;
        } else if (left == -mRange) {
            return Status.OPEN;
        } else {
            return Status.DRAGING;
        }
    }

    @Override
    public void computeScroll() {
        super.computeScroll();

        if (mViewDragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }

    public void close() {
        close(true);
    }

    private void close(boolean isSmooth) {
        if (isSmooth) {
            if (mViewDragHelper.smoothSlideViewTo(frontView, 0, 0)) {
                ViewCompat.postInvalidateOnAnimation(this);
            }
        } else {
            layoutViews(false);
        }
    }

    private void open() {
        open(true);
    }

    private void open(boolean isSmooth) {
        if (isSmooth) {
            if (mViewDragHelper.smoothSlideViewTo(frontView, -mRange, 0)) {
                ViewCompat.postInvalidateOnAnimation(this);
            }
        } else {
            layoutViews(true);
        }
    }

    private int computeLeft(int left) {
        if (left < mWidth - mRange) {
            return mWidth - mRange;
        } else if (left > mWidth) {
            return mWidth;
        } else {
            return left;
        }
    }

    private int fixLeft(int left) {
        if (left > 0) {
            return 0;
        } else if (left < -mRange) {
            return -mRange;
        } else {
            return left;
        }
    }

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


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

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

        //第一步:初始化ViewDragHelper的实例对象
        mViewDragHelper = ViewDragHelper.create(this, mCallback);
    }

    //第二步:托管触摸事件
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mViewDragHelper.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        try {
            mViewDragHelper.processTouchEvent(event);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        if (getChildCount() < 2) {
            throw new IllegalArgumentException("This ViewGroup must have two childern at least!");
        }

        if (!(getChildAt(0) instanceof ViewGroup) || !(getChildAt(1) instanceof ViewGroup)) {
            throw new IllegalArgumentException("The children must be instanceof ViewGroup!");
        }

        backView = (ViewGroup) getChildAt(0);
        frontView = (ViewGroup) getChildAt(1);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();

        mRange = backView.getMeasuredWidth();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        layoutViews(false);
    }

    /**
     * 初始化控件的位置
     *
     * @param isOpen
     */
    private void layoutViews(boolean isOpen) {
        Rect backRect = layoutBackView(isOpen);
        backView.layout(backRect.left, backRect.top, backRect.right, backRect.bottom);

        Rect frontRect = layoutFrontView(isOpen);
        frontView.layout(frontRect.left, frontRect.top, frontRect.right, frontRect.bottom);
    }

    private Rect layoutBackView(boolean isOpen) {
        int newLeft = mWidth;
        if (isOpen) {
            newLeft = mWidth - mRange;
        }
        return new Rect(newLeft, 0, newLeft + mWidth, mHeight);
    }

    private Rect layoutFrontView(boolean isOpen) {
        int newLeft = 0;
        if (isOpen) {
            newLeft = -mRange;
        }
        return new Rect(newLeft, 0, newLeft + mWidth, mHeight);
    }
}

MyAdapter:
package com.hxht.testlvwithdragmessageitem.adapter;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.hxht.testlvwithdragmessageitem.R;
import com.hxht.testlvwithdragmessageitem.customview.DragMessageView;

import java.util.HashSet;
import java.util.List;

public class MyAdapter extends BaseAdapter {

    private List<String> list;
    private Context context;
    private HashSet<DragMessageView> set = new HashSet<>();

    public MyAdapter(List<String> list, Context context) {
        this.list = list;
        this.context = context;
    }

    @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) {
        View view = null;
        if (convertView == null) {
            view = View.inflate(context, R.layout.activity_main, null);
        } else {
            view = convertView;
        }

        final DragMessageView dragMessageView = (DragMessageView) view;
        dragMessageView.setmOnDragChangeListener(new DragMessageView.OnDragChangeListener() {

            @Override
            public void onOpen() {
                set.add(dragMessageView);
            }

            @Override
            public void onClose() {
                set.remove(dragMessageView);
            }

            @Override
            public void onDraging() {
                for (DragMessageView dragview : set) {
                    dragview.close();
                }
            }
        });

        ViewHolder holder = ViewHolder.getHolder(view);
        holder.tv.setText(list.get(position));
        holder.tv_tofirst.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Toast.makeText(context, "当前条目" + position + "----置顶", Toast.LENGTH_SHORT).show();
                String str = list.get(position);
                list.remove(str) ;
                list.add(0, str);
                MyAdapter.this.notifyDataSetChanged();
            }
        });

        holder.tv_todelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Toast.makeText(context, "当前条目" + position + "----删除", Toast.LENGTH_SHORT).show();
                list.remove(position);
                MyAdapter.this.notifyDataSetChanged();
            }
        });

        return view;
    }

    private static class ViewHolder {

        TextView tv;
        TextView tv_tofirst;
        TextView tv_todelete;

        public ViewHolder(TextView tv, TextView tv_tofirst, TextView tv_todelete) {
            this.tv = tv;
            this.tv_tofirst = tv_tofirst;
            this.tv_todelete = tv_todelete;
        }

        public static ViewHolder getHolder(View view) {
            Object tag = view.getTag();
            if (tag != null) {
                return ((ViewHolder) tag);
            } else {
                return new ViewHolder((
                        (TextView) view.findViewById(R.id.tv)),
                        ((TextView) view.findViewById(R.id.tv_tofirst)),
                        ((TextView) view.findViewById(R.id.tv_todelete)));
            }
        }
    }
}

布局文件:
activity_main.xml
<com.hxht.testlvwithdragmessageitem.customview.DragMessageView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/dragmessageview"
    android:layout_width="match_parent"
    android:splitMotionEvents="false"
    android:layout_height="wrap_content"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/backview"
        android:layout_width="160dip"
        android:layout_height="60dip"
        android:orientation="horizontal"
        android:weightSum="2">

        <TextView
            android:id="@+id/tv_tofirst"
            android:layout_width="80dip"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:background="#999999"
            android:gravity="center"
            android:text="置顶"
            android:textColor="#FFFFFF"
            android:textSize="24dp" />

        <TextView
            android:id="@+id/tv_todelete"
            android:layout_width="80dip"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:background="#ff0000"
            android:gravity="center"
            android:text="删除"
            android:textColor="#ffffff"
            android:textSize="24dp" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/frontview"
        android:layout_width="match_parent"
        android:layout_height="60dip"
        android:background="#A3AF91"
        android:orientation="horizontal">

        <de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/profile_image"
            android:layout_width="45dip"
            android:layout_height="45dip"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="45dip"
            android:src="@mipmap/iv_bg"
            app:border_color="#FF000000"
            app:border_width="2dp" />

        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="30dip"
            android:gravity="center_vertical"
            android:text="宋江"
            android:textColor="#ffffff"
            android:textSize="26dp" />
    </LinearLayout>
</com.hxht.testlvwithdragmessageitem.customview.DragMessageView>

activity_lv.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="match_parent"
    android:splitMotionEvents="false"
    android:orientation="vertical">

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

效果图如下:


代码已贴出,正所谓取之于社会,回报于社会,还望各位大神批评指正,多多指教,不喜勿喷,灰常感谢 O(∩_∩)O哈哈~
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值