• 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的扩展类里覆盖就行。

  • 相关阅读:
    转载:div和flash层级关系问题
    转载:页面加载swf插件:swfobject
    C++ code:浮点数的比较(Floating-Pointing Number Comparison)
    Deep Learning系统实训之三:卷积神经网络
    C++ code:指针类型(pointer types)
    Linear Algebra(未完待续)
    Deep Learning系统实训之二:梯度下降原理
    C++ code:向量操作之添加元素
    Deep Learning系统实训之一:深度学习基础知识
    机器学习与优化关系、凸集、凸函数简介
  • 原文地址:https://www.cnblogs.com/bvin/p/3153191.html
Copyright © 2020-2023  润新知