listview侧滑菜单的实现——高仿QQ联系人列表

本文介绍如何实现类似QQ联系人列表的ListView侧滑菜单功能。通过自定义ViewGroup处理TouchEvent,利用dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent方法控制事件分发,避免水平与垂直滑动冲突。详细讲解了实现原理,并提供了代码示例。
摘要由CSDN通过智能技术生成

转载请注明出处:http://blog.csdn.net/binbinqq86/article/details/46010951

 

项目用到了ListView的侧滑删除的功能,由于当时项目比较赶,就随便在网上找了一个,但是效果不是太好,最近闲了下来,就想自己实现一个,于是就按照QQ的联系人列表的侧滑菜单做了一个,效果基本上是一模一样的。在这个过程中,自己也学习到了不少的东西,下面就把这个过程跟大家分享出来。

 

废话不多说,首先上效果图。

 

 

 

看完了图如果感觉效果不好,请不要拍砖,奋斗好的话请继续往下看~得意

 

下面结合代码说说实现的原理:首先自定义一个ViewGroup来实现item的滑动效果。

 

 

package com.binbin.slidedelmenu.item;  
  
import android.content.Context;  
import android.os.Build;  
import android.support.annotation.RequiresApi;  
import android.support.v4.widget.ViewDragHelper;  
import android.util.AttributeSet;  
import android.util.Log;  
import android.view.GestureDetector;  
import android.view.MotionEvent;  
import android.view.VelocityTracker;  
import android.view.View;  
import android.view.ViewConfiguration;  
import android.view.ViewGroup;  
import android.widget.BaseAdapter;  
import android.widget.FrameLayout;  
import android.widget.ListAdapter;  
import android.widget.ListView;  
import android.widget.Scroller;  
  
/** 
 * Created by -- on 2016/11/3. 
 * 带侧滑菜单的自定义item 
 */  
  
public class MenuItem extends ViewGroup {  
    private int contentWidth;  
    private Scroller mScroller;  
    private int maxWidth,maxHeight;//viewGroup的宽高  
    private static final int MIN_FLING_VELOCITY = 600; // dips per second  
    /**最小滑动距离,超过了,才认为开始滑动  */  
    private int mTouchSlop = 0 ;  
    /**上次触摸的X坐标*/  
    private float mLastX = -1;  
    /**第一次触摸的X坐标*/  
    private float mFirstX = -1;  
    private int ratio;  
    //防止多只手指一起滑动的flag 在每次down里判断, touch事件结束清空  
    private static boolean isTouching;  
    private int mRightMenuWidths;//右侧菜单总宽度  
    private VelocityTracker mVelocityTracker;  
    private float mMaxVelocity;  
    private int mPointerId;//多点触摸只算第一根手指的速度  
    private boolean isQQ=true;//是否是qq效果  
    private boolean qqInterceptFlag;//qq效果判断标志  
    private static MenuItem mViewCache;//存储的是当前正在展开的View  
    private boolean isUserSwiped;// 判断手指起始落点,如果距离属于滑动了,就屏蔽一切点击事件  
    //仿QQ,侧滑菜单展开时,点击除侧滑菜单之外的区域,关闭侧滑菜单。  
    //增加一个布尔值变量,dispatch函数里,每次down时,为true,move时判断,如果是滑动动作,设为false。  
    //在Intercept函数的up时,判断这个变量,如果仍为true 说明是点击事件,则关闭菜单。  
    private boolean isUnMoved = true;  
  
    public MenuItem(Context context) {  
        this(context,null);  
    }  
  
    public MenuItem(Context context, AttributeSet attrs) {  
        this(context, attrs,0);  
    }  
  
    public MenuItem(Context context, AttributeSet attrs, int defStyleAttr) {  
        super(context, attrs, defStyleAttr);  
        init();  
    }  
  
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)  
    public MenuItem(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {  
        super(context, attrs, defStyleAttr, defStyleRes);  
        init();  
    }  
  
    private void init(){  
        contentWidth=getContext().getResources().getDisplayMetrics().widthPixels;  
        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();  
        mScroller=new Scroller(getContext());  
        mMaxVelocity = ViewConfiguration.get(getContext()).getScaledMaximumFlingVelocity();  
    }  
  
    @Override  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
        setClickable(true);//令自己可点击,从而获取触摸事件(很重要,必须写在onMesaure中)  
        mRightMenuWidths=0;//由于ViewHolder的复用机制,每次这里要手动恢复初始值  
        /** 
         * 根据childView计算的出的宽和高,计算容器的宽和高,主要用于容器是warp_content时 
         */  
        for (int i = 0,count = getChildCount(); i < count; i++) {  
            View childView = getChildAt(i);  
            //令每一个子View可点击,从而获取触摸事件  
            childView.setClickable(true);  
            if(childView.getVisibility()!=View.GONE){  
                //获取每个子view的自己高度宽度,取最大的就是viewGroup的大小  
                measureChild(childView, widthMeasureSpec, heightMeasureSpec);  
                maxWidth = Math.max(maxWidth,childView.getMeasuredWidth());  
                maxHeight = Math.max(maxHeight,childView.getMeasuredHeight());  
                if(i>0){//第一个是content,后面的都是菜单  
                    if(childView.getLayoutParams().width== LayoutParams.MATCH_PARENT){  
                        //菜单的宽不能MATCH_PARENT  
                        throw new IllegalArgumentException("======menu'width can't be MATCH_PARENT=====");  
                    }  
                    mRig
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值