AndroidのListView之滑动列表项(点击事件和滑动事件共存)
这里正好在项目有这么一个bt的需求,如下图ListView的item可以响应点击事件也可以响应item的左右滑动事件,两个事件可以相互独立互不影响。
听说iphone的list选项就有这样bt的功能,安卓版的手机QQ和微信和QQ通讯录也有类似的效果,在网上各种寻早方案都试过,要不只能滑动不能点击要么就只能点击不能滑动,而且操作很不灵敏,网上的代码都是在itemView的onTouch方法里处理,判断down和up的像素差。其实这样操作相当不便,down-up这样的其实只能算拖动事件而不是滑动事件,所以你会联想到scroll和fling的区别。

大家可以看看我之前的做法,使用ontouch方法处理的,很难独立滑动事件跟点击事件,就算可以滑动也是很灵敏,操作10次难得一次成功。
class SwipeListener implements View.OnTouchListener{
        ViewHolder holder;
        HouseList_Item item;
        int startX = 0;
        int endX = 0;
        public SwipeListener(ViewHolder holder, HouseList_Item item) {
            super();
            this.holder = holder;
            this.item = item;
        }
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            if(event.getAction() == MotionEvent.ACTION_DOWN){
                startX = (int)event.getX();
                Debuger.log_e("startX", ""+startX);
                return true;
            }else if(event.getAction() == MotionEvent.ACTION_UP){
                endX = (int)event.getX();
                Debuger.log_e("endX", ""+endX);
                if(startX - endX > 120){
                    Debuger.log_e("触发", "左划");
                    holder.llMenu.setVisibility(View.VISIBLE);
                    return false;
                }else if(endX - startX >120){
                    Debuger.log_e("触发", "右划");
                    holder.llMenu.setVisibility(View.GONE);
                    return true;
                }else{
                    Toast.makeText(ctx, "点击item", 3000).show();
                    return true;
                }
            }
            return true;
        }
    }
代码有注释相信大家都看得懂,像上面这样子也差不多让滑动事件和点击事件独立出来了。一开始还傻乎乎的用ListView的OnItemClick事件,搭配这样功能真的是碉堡。
经过半天的努力探索,今天终于很流畅得实现这效果。下面是新的代码:
这个是适配器的代码,有部分省略,主要是GestureDetector 这样一个手势监听器。
public class HouseList_Adapter extends BaseAdapter{
    private GestureDetector detector;
    private List<HouseList_Item> list ;
    private Context ctx = null;
    private LayoutInflater inflater = null;
    FlingListeber listener;
    public HouseList_Adapter( Context ctx,List<HouseList_Item> list) {
        super();
        this.list = list;
        this.ctx = ctx;
        inflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        listener = new FlingListeber();
        detector = new GestureDetector(listener);
    }
    @Override
    public View getView(int arg0, View arg1, ViewGroup arg2) {
        // TODO Auto-generated method stub
        ViewHolder holder = null;
        if(arg1==null){
            arg1 = inflater.inflate(R.layout.house_item_layout, null);
            holder = new ViewHolder();
            holder.llItem = (LinearLayout)arg1.findViewById(R.id.llItem);
            holder.tvTitle = (TextView)arg1.findViewById(R.id.tvTitle);
            holder.tvBuildeArea = (TextView)arg1.findViewById(R.id.tvArea);
            holder.tvPrice = (TextView)arg1.findViewById(R.id.tvPrice);
            holder.tvPriceUnit = (TextView)arg1.findViewById(R.id.tvPriceUnit);
            holder.tvRoom = (TextView)arg1.findViewById(R.id.tvRoom);
            holder.llFlag = (LinearLayout)arg1.findViewById(R.id.llFlag);
            holder.ivFlag1 = (ImageView)arg1.findViewById(R.id.ivFlag1);
            holder.ivFlag2 = (ImageView)arg1.findViewById(R.id.ivFlag2);
            holder.ivFlag3 = (ImageView)arg1.findViewById(R.id.ivFlag3);
            holder.ivFlag4 = (ImageView)arg1.findViewById(R.id.ivFlag4);
            holder.llMenu = (LinearLayout)arg1.findViewById(R.id.house_ltem_menu);
            holder.ivCall = (Button)arg1.findViewById(R.id.ivCall);
            holder.ivDetails = (Button)arg1.findViewById(R.id.ivCall);
            holder.ivMap = (Button)arg1.findViewById(R.id.ivMap);
            holder.ivSend = (Button)arg1.findViewById(R.id.ivSend);
            arg1.setTag(holder);
        }else{
            holder = (ViewHolder)arg1.getTag();
        }
        final HouseList_Item item = list.get(arg0);
        listener.setItem(item);
        //holder.llItem.setOnTouchListener(new SwipeListener(holder,item));
        holder.llItem.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // TODO Auto-generated method stub
                return detector.onTouchEvent(event);
            }
        });
     }
        class FlingListeber implements GestureDetector.OnGestureListener{
        HouseList_Item item;
        ViewHolder holder;
        public HouseList_Item getItem() {
            return item;
        }
        public void setItem(HouseList_Item item) {
            this.item = item;
        }
        public ViewHolder getHolder() {
            return holder;
        }
        public void setHolder(ViewHolder holder) {
            this.holder = holder;
        }
        @Override
        public boolean onDown(MotionEvent e) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {
            // TODO Auto-generated method stub
            if(e2.getX()-e1.getX()>20){
                Toast.makeText(ctx, "左滑"+item.areaName, 3000).show();
            }else if(e1.getX()-e2.getX()>20){
                Toast.makeText(ctx, "右滑"+item.areaName, 3000).show();
            }
            return false;
        }
        @Override
        public void onLongPress(MotionEvent e) {
            // TODO Auto-generated method stub
        }
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                float distanceX, float distanceY) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public void onShowPress(MotionEvent e) {
            // TODO Auto-generated method stub
        }
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            // TODO Auto-generated method stub
            Toast.makeText(ctx, "点击item", 3000).show();
            return false;
        }
    }
}        
这样让item的滑动事件交给onFling去处理,点击事件交给onSingleTapUp这样就可以让两个事件相互独立了,但是这样执行发现还是会有很不顺畅滑动的时候,后来我一想那肯定是listview的上下滑动跟item的左右滑动事件有冲突,所以就把之前定义的一个ScrollView里处理touch事件拷过去就很灵敏了,百发百中。
// 滑动距离及坐标
private float xDistance, yDistance, xLast, yLast;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
xLast = ev.getX();
yLast = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY(); xDistance += Math.abs(curX - xLast);
yDistance += Math.abs(curY - yLast);
xLast = curX;
yLast = curY; if(xDistance > yDistance){
return false;
}
} return super.onInterceptTouchEvent(ev);
}
把这段代码复制到一个ListView的扩展类里覆盖就行。
AndroidのListView之滑动列表项(点击事件和滑动事件共存)的更多相关文章
- Android学习笔记(23):列表项的容器—AdapterView的子类们
		
AdapterView的子类的子类ListView.GridView.Spinner.Gallery.AdapterViewFlipper和StackView都是作为容器使用,Adapter负责提供各 ...
 - Android ListView 长按列表弹出菜单
		
Android ListView 长按列表弹出菜单 设置长按菜单 listView.setOnCreateContextMenuListener(new View.OnCreateContextMen ...
 - PyQt学习随笔:QtDesigner ListView控件列表项的初始化
		
在QtDesigner中设计的界面中添加ListView控件后,是没办法添加需要在ListView控件中显示的列表项.由于ListView控件只是一个展示列表项的视图控件,实现了界面与数据的分离,其要 ...
 - Android ListView中 每一项都有不同的布局
		
实现代码 Adapter的代码 其中:ViewHolder分别是三个不同的布局,也就是ListView中每一项的布局 TYPE_1...是三种类型. 在使用不同布局的时候,getItemViewTyp ...
 - android listview里包含组件(checkbox)点击事件和Item的点击事件冲突
		
在listview的item中包含有textview和checkBox.我们既想获取listitem的点击事件,又想获取listitem中textview的点击事件和listitem中checkBox ...
 - 建立CMenu菜单项,实现选中菜单项点击左键响应事件
		
这里我只是根据自己的项目做了一些总结,实现点击右键弹出菜单项,点左键选择菜单项: CMenu menu; VERIFY(menu.CreatePopupMenu());//新建一个cmenu菜单项 m ...
 - android Listview item 中有button,item就不响应触摸事件
		
为button设置 beanButton.getButton().setFocusable(false); beanButton.getButton().setFocusableInTouchMode ...
 - Android开发 ExpandableListView 可折叠列表详解
		
前言 在需要实现一个List的item需要包含列表的时候,我们就可以选择ExpandableListView. 其实这个View的原始设计还是ListView的那套.就是增加2层的ListView而已 ...
 - Android ListView焦点事件冲突问题与解决
		
Android ListView对于单纯列表展示是很好用的,但是一旦牵扯到对listView进行操作就会遇到各种各样的问题.比如保存Checkbox状态与item复用的冲突.遇到可获取焦点的控件比如说 ...
 
随机推荐
- Java中HashMap实现原理
			
类声明: 概述: 线程不安全: <Key, Value>两者都可以为null: 不保证映射的顺序,特别是它不保证该顺序恒久不变: HashMap使用Iterator: HashMap中ha ...
 - 细数JDK里的设计模式<转>
			
这也是篇老文了,相信很多人也看过.前面那些废话就不翻译了,直接切入正题吧~ 结构型模式: 适配器模式: 用来把一个接口转化成另一个接口. java.util.Arrays#asList() javax ...
 - Hive Tunning(二)优化存储
			
接着上一章我们讲的hive的连接策略,现在我们讲一下hive的数据存储. 下面是hive支持的数据存储格式,有我们常见的文本,JSON,XML,这里我们主要讲一下ORCFile. Built-in F ...
 - day day up
			
复位与时钟控制器 RCC(Reset Clock Controller) 通用输入输出 GPIO(General Purpose Input/Output) 嵌套向量中断控制器 NVIC(Nested ...
 - 几种常见的DIV边框样式
			
<html> <head> <title>边框样式</title> </head> <body> <p style=bor ...
 - h264 i p 帧特点
			
1.爱无铭(47530789) 2014-2-13 17:07:27 I帧只有intra p帧有inter和intra:B帧一般只用inter 2. 庐舍闲士(361389535) 2014-2 ...
 - nodejs基础 -- 回调函数
			
Node.js 异步编程的直接体现就是回调. 异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了. 回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都 ...
 - jQuery中return false,e.preventDefault(),e.stopPropagation()的区别
			
e.stopPropagation()阻止事件冒泡 <head> <title></title> <script src="Scripts/jQue ...
 - PHP curl_setopt函数用法介绍补充篇
			
1.curl数据采集系列之单页面采集函数get_html 单页面采集在数据采集过程中是最常用的一个功能 有时在服务器访问限制的情况下 只能使用这种采集方式 慢 但是可以简单的控制 所以写好一个常用的c ...
 - dwr框架使用总结——简单示例
			
1.新建web项目,项目名为dwr 2.导入以下jar包: dwr.jar.classes12.jar.commons-logging-1.0.4.jar和commons-logging.jar 3. ...