Android手势(二)

原创 2015年07月07日 11:33:25
 
在上文中我们对手势操作进行了基本验证,
我们将上文中添加第二个textview的改为添加Listview,代码如下:
Java代码 复制代码 收藏代码Android手势(二)
  1. ListView lv = new ListView(this);   
  2. lv.setBackgroundColor(0xff808080);   
  3. final String[] items = {"one""two""three"};   
  4. lv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items));   
  5. mVf.addView(lv,new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));  
ListView lv = new ListView(this);
lv.setBackgroundColor(0xff808080);
final String[] items = {"one", "two", "three"};
lv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items));
mVf.addView(lv,new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

执行ap,滑动屏幕切换到第二屏,可以看到第二屏被换成了一个ListView,
并且没有填充完整个屏幕,这时如果在底部非ListView区域向左滑动,
仍然可以切换到第一屏,但是在Listview区域滑动就没有效果了,
因为touch事件被Listview处理了,ViewFlipper无法收到touch事件也就无法进行手势判断。
我们给ListView也增加一个touch事件监听器,代码如下:
Java代码 复制代码 收藏代码Android手势(二)
  1. lv.setOnTouchListener(new OnTouchListener() {              
  2.     @Override  
  3.     public boolean onTouch(View v, MotionEvent event) {   
  4.         return mVfDetector.onTouchEvent(event);   
  5.     }   
  6. });  
lv.setOnTouchListener(new OnTouchListener() {                     
        @Override
        public boolean onTouch(View v, MotionEvent event) {
                return mVfDetector.onTouchEvent(event);
        }
});

此时在ListView上滑动也能实现屏幕切换了。
我们再给Listview增加响应点击事件的处理,代码如下:
Java代码 复制代码 收藏代码Android手势(二)
  1. lv.setOnItemClickListener(new OnItemClickListener() {   
  2.     @Override  
  3.     public void onItemClick(AdapterView<?> arg0, View arg1,    
  4.         int arg2, long arg3) {   
  5.         new AlertDialog.Builder(MainActivity.this)   
  6.             .setMessage(items[arg2])   
  7.             .create()   
  8.             .show();                   
  9.     }   
  10. });  
lv.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, 
                int arg2, long arg3) {
                new AlertDialog.Builder(MainActivity.this)
                        .setMessage(items[arg2])
                        .create()
                        .show();                                
        }
});

当点击Listview的条目的时候,就会弹出窗口显示点击了哪一项,此时的代码可参见附件1。
截止到此时,似乎Listview支持左右滑动的操作完成了,但实际上仍有两个问题:
首先就是滑动时,Listview有时会有条目被高亮,这个问题倒还不是太严重。
再次就是ContextMenu每次滑动都会被激活,我们可以通过代码验证,
创建ListView的代码稍作修改:
Java代码 复制代码 收藏代码Android手势(二)
  1. //使Listview长一些   
  2. final String[] items = {"one""two""three""four""five""six""sevent""eight""nine"};    
  3. registerForContextMenu(lv);  
//使Listview长一些
final String[] items = {"one", "two", "three", "four", "five", "six", "sevent", "eight", "nine"}; 
registerForContextMenu(lv);

另外Activity的代码增加:
Java代码 复制代码 收藏代码Android手势(二)
  1. @Override  
  2. public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {   
  3.         menu.add("Menu 1");   
  4.         menu.add("Menu 2");   
  5.         menu.add("Menu 3");   
  6.     super.onCreateContextMenu(menu, v, menuInfo);   
  7. }  
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        menu.add("Menu 1");
        menu.add("Menu 2");
        menu.add("Menu 3");
        super.onCreateContextMenu(menu, v, menuInfo);
}

当我们在ListView的某一项上长按时就会弹出菜单,
但是当滑动时,即使屏幕切换到了第一屏,此菜单仍然会弹出。
此时的验证代码参加附件2。
PS:现在的解决方法:
Java代码 复制代码 收藏代码Android手势(二)
  1. getListView().setOnTouchListener(new OnTouchListener() {   
  2.         @Override  
  3.         public boolean onTouch(View v, MotionEvent event) {   
  4.             if( mDetector.onTouchEvent(event) ) {   
  5.                 MotionEvent cancelEvent = MotionEvent.obtain(event);   
  6.                 cancelEvent.setAction(MotionEvent.ACTION_CANCEL);   
  7.                 v.onTouchEvent(cancelEvent);   
  8.                 return true;   
  9.             }   
  10.             return false;   
  11.         }   
  12.     });  
 getListView().setOnTouchListener(new OnTouchListener() {
                        @Override
                        public boolean onTouch(View v, MotionEvent event) {
                                if( mDetector.onTouchEvent(event) ) {
                                        MotionEvent cancelEvent = MotionEvent.obtain(event);
                                        cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
                                        v.onTouchEvent(cancelEvent);
                                        return true;
                                }
                                return false;
                        }
                });

当判断出是手势事件后,用CANCEL事件吃掉就不会导致菜单弹出了。

为了解决上面的问题,我尝试了以下办法:
1.在ListView的touch事件监听函数中始终返回true,吃掉所有事件,
这样的修改导致不能相应点击,ListView不能上下滑动,此路不通。
2.在GestureDetector的fling函数中向ListView发送一个MotionEvent.ACTION_CANCEL事件,
总是空指针异常,怀疑是因为touch事件没有被ListView处理过,其内部成员状态异常,
于是我从ListView继承实现了一个ListView,在onTouchEvent中呼叫super.onTouchEvent,但是发送MotionEvent.ACTION_CANCEL事件时仍然是空指针异常,再次失败。
3.GestureDetector的onDown函数返回true,吃掉down事件,此时点击时没有高亮项了,
切换时contextmenu也不被trigger了,但是长按也无法弹出contextmenu了。
为了能弹出contextMenu,那么就要在GestureDetector的onLongPress函数中调用ListView.showContextMenuForChild()来弹出菜单,
那么GestureDetector就与ViewFlipper的不通用了,
所以我重新由ListView继承实现了一个类,这个类自身绑定了一个GestureDetector:
Java代码 复制代码 收藏代码Android手势(二)
  1. @Override  
  2. public boolean onDown(MotionEvent e) {   
  3.     return true;    //吃掉Down事件   
  4. }   
  5. @Override  
  6. public void onLongPress(MotionEvent e) {       
  7.     System.out.println("Listview long press");   
  8.     int position = pointToPosition((int)e.getX(), (int)e.getY());                  
  9.     if( position != ListView.INVALID_POSITION) {   
  10.         View child = getChildAt(position - getFirstVisiblePosition());   
  11.         if(child != null) GestureListView.this.showContextMenuForChild(child);   
  12.     }   
  13. }  
@Override
public boolean onDown(MotionEvent e) {
        return true;    //吃掉Down事件
}
@Override
public void onLongPress(MotionEvent e) {        
        System.out.println("Listview long press");
        int position = pointToPosition((int)e.getX(), (int)e.getY());                           
        if( position != ListView.INVALID_POSITION) {
                View child = getChildAt(position - getFirstVisiblePosition());
                if(child != null) GestureListView.this.showContextMenuForChild(child);
        }
}

另外为了能够显示contextmenu时在哪一项上激活的,在Activity增加函数:
Java代码 复制代码 收藏代码Android手势(二)
  1. @Override  
  2. public boolean onContextItemSelected(MenuItem item) {   
  3.     AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();   
  4.     System.out.println("View " + info.position + " context menu activited.");   
  5.     return super.onContextItemSelected(item);   
  6. }  
@Override
public boolean onContextItemSelected(MenuItem item) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        System.out.println("View " + info.position + " context menu activited.");
        return super.onContextItemSelected(item);
}

从LogCat即可看到打印输出。
此时此ListView可以响应手势、可以响应点击、可以弹出菜单,
基本的功能已经满足,另外再微调一下ondown函数,当点击时可以高亮一下。
最终代码可参见附件3。
PS:
最好的办法还是直接从AbsListView来修改,将左右方向手势判断加入进去,待研究。
 
版权声明:本文为博主原创文章,未经博主允许不得转载。

Android手势事件分发过程分析

Android手势事件传递分析
  • xu_fu
  • xu_fu
  • 2014年06月21日 18:02
  • 4247

Android最佳实践之触摸手势

普通手势参考地址:http://developer.android.com/training/gestures/detector.html#data 当用户一根或多根手指在屏幕上运动的时候,就开始产...
  • ada_dengpan
  • ada_dengpan
  • 2016年04月10日 00:27
  • 7429

Android 手势操作GestureDetector

在很多应用中我们经常会看到一些不同手势的点击事件,例如QQ的消息列表,我们可以通过左滑消息来选择删除或者置顶或者标记为已读,我们也可以通过右滑拖出QQ菜单。有些应用中还会有长按,双击等手势。但是一般情...
  • To_be_Designer
  • To_be_Designer
  • 2015年09月24日 19:47
  • 2232

Android练习之手势绘制图案

我们都知道绘制图案就不可少的几样工具,一个是画笔(Paint),一个是画布(Canvas),画布就是在屏幕上添加一块布,然后用画笔在上面画画,当然我们需要设置画笔的颜色,字体大小,字体的样式等等 /...
  • lovemy_baby
  • lovemy_baby
  • 2017年09月01日 11:05
  • 90

Android 不同手势的识别:滑动、放大缩小

Demo地址:http://download.csdn.net/detail/baopengjian/9670309一、需求:识别:单指 上滑、下滑、左移、右移、长按多指 放大、缩小、长按二、实现:自...
  • baopengjian
  • baopengjian
  • 2016年11月01日 17:56
  • 2220

Android视频播放器的手势控制实现

出处: 炎之铠邮箱:yanzhikai_yjk@qq.com 博客地址:http://blog.csdn.net/totond 本文原创,转载请注明本出处! 本项目GitHub...
  • totond
  • totond
  • 2017年09月07日 14:41
  • 1856

Android官方开发文档Training系列课程中文版:手势处理之拖拽或缩放

原文地址:http://android.xsoftlab.net/training/gestures/scale.html 这节课主要学习如何使用触摸手势来拖动或者放大屏幕上的对象,以及使用onTo...
  • u011064099
  • u011064099
  • 2016年08月12日 10:33
  • 1454

Android : GestureDetector手势检测

关于Android的手势检测方面,刚开始的时候感觉自己还有点误区,认为onTouchEvent方法中的ACTION_DOWN、ACTION_UP、ACTION_MOVE也算是手势,实际上Android...
  • danfengw
  • danfengw
  • 2015年09月24日 17:35
  • 1088

Android事件传递机制、手势检测

领卓教育培训第七十三天 机制介绍分析我看了一篇博客,写的非常详细,而且通俗易懂! http://blog.csdn.net/morgan_xww/article/details/9372285/简单...
  • aiynmimi
  • aiynmimi
  • 2015年09月24日 19:58
  • 949

Android view手势拖动和缩放

在实际开发中很多地方都要用自定义的手势缩放和可移动的view,在下在开发不久的时候就遇到啦,当时还不懂手势拖动,经过了各种摸索和查阅终于是自己写出来了,感觉收获颇多,这里我是用的矩阵来对自定义的Ima...
  • CoderYue
  • CoderYue
  • 2016年03月11日 22:53
  • 4074
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android手势(二)
举报原因:
原因补充:

(最多只允许输入30个字)