zoukankan      html  css  js  c++  java
  • 窗口的基本手势事件处理

    当用户触摸屏幕时会产生很多的触摸事件,down、up、move等等。View类有个View.OnTouchListener内部接口,通过重写他的onTouch(View v, MotionEvent event)方法,我们可以处理一些touch事件,如下是activity的ontouch方法里调用的是super.onTouchEvent(),因此直接覆写onTouchEvent():

    1简单的监听

    public class MainActivity extends Activity {  
    ...  
    // This example shows an Activity, but you would use the same approach if  
    // you were subclassing a View.  
    @Override  
    public boolean onTouchEvent(MotionEvent event){   
              
        int action = MotionEventCompat.getActionMasked(event);  
              
        switch(action) {  
            case (MotionEvent.ACTION_DOWN) :  
                Log.d(DEBUG_TAG,"Action was DOWN");  
                return true;  
            case (MotionEvent.ACTION_MOVE) :  
                Log.d(DEBUG_TAG,"Action was MOVE");  
                return true;  
            case (MotionEvent.ACTION_UP) :  
                Log.d(DEBUG_TAG,"Action was UP");  
                return true;  
            case (MotionEvent.ACTION_CANCEL) :  
                Log.d(DEBUG_TAG,"Action was CANCEL");  
                return true;  
            case (MotionEvent.ACTION_OUTSIDE) :  
                Log.d(DEBUG_TAG,"Movement occurred outside bounds " +  
                        "of current screen element");  
                return true;        
            default :   
                return super.onTouchEvent(event);  
        }        
    }  
    

      (2)复杂监听

      OnTouch提供的事件还是相对较简单,如果需要处理一些复杂的手势,用这个接口就会很麻烦,因为我们要根据用户触摸的轨迹去判断是什么手势。Android sdk给我们提供了GestureDetector(Gesture:手势Detector:识别)类,通过这个类我们可以识别很多的手势。 GestureDetector属于android.view包,android还提供了android.gesture包支持更多的手势操作,以后我们会介绍到。官方的介绍中使用了GestureDetectorCompat处理手势识别,使用GestureDetectorCompat替换。

    GestureDetector类对外提供了两个接口:OnGestureListener,OnDoubleTapListener,还有一个内部类SimpleOnGestureListener;SimpleOnGestureListener类是GestureDetector提供给我们的一个更方便的响应不同手势的类,它实现了上述两个接口,该类是static class,也就是说它实际上是一个外部类,我们可以在外部继承这个类,重写里面的手势处理方法。因此实现手势识别有两种方法,一种实现OnGestureListener接口,另一种是使用SimpleOnGestureListener类。

    OnGestureListener有下面的几个动作:

    按下(onDown): 刚刚手指接触到触摸屏的那一刹那,就是触的那一下。

    抛掷(onFling): 手指在触摸屏上迅速移动,并松开的动作。

    长按(onLongPress): 手指按在持续一段时间,并且没有松开。

    滚动(onScroll): 手指在触摸屏上滑动。

    按住(onShowPress): 手指按在触摸屏上,它的时间范围在按下起效,在长按之前。

    抬起(onSingleTapUp):手指离开触摸屏的那一刹那。

        使用OnGestureListener接口,这样需要重载OnGestureListener接口所有的方法,适合监听所有的手势,正如官方文档提到的“Detecing All Supported Gestures”。值得注意的是:它也是通过覆写onTouchEvent来处理事件的,如果不在onTouchEvent里处理,下面的事件里的System.out.println()是打不出来的,里面的动作也不会执行。

    我的一个demo如下:在双击屏幕时候会拨打电话。

    public class MainActivity extends Activity implements OnGestureListener,OnDoubleTapListener
    {
    	private GestureDetectorCompat mDetector; 
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
             
            mDetector=new GestureDetectorCompat(this,this); 
            mDetector.setOnDoubleTapListener(this);
        }
     
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            //这里面处理GestureDetectorCompat调用listener监听到的事件,若这里不调用下面的这个函数,下面监听到的事件也是不会处理的
        	//就是说GestureDetectorCompat的原理也是调用onTouch来处理的。
        	this.mDetector.onTouchEvent(event);
        	 return super.onTouchEvent(event);  
        }
      
     
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            Log.d("erro", "onSingleTapConfirmed: " + e.toString());
            return true;
        }
     
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            // TODO Auto-generated method stub
            System.out.println("双击了...");
            return true;
        }
     
        @Override
        public boolean onDoubleTapEvent(MotionEvent e) {
        	Intent intent =new Intent();
        	intent.setAction(Intent.ACTION_CALL);
        	intent.setData(Uri.parse("tel:"+15607209));
        	startActivity(intent);
            System.out.println("双击事件完成...");
            return true;
        }
     
        @Override
        public boolean onDown(MotionEvent e) {
            System.out.println("落下屏幕时候...");
            return false;
        }
     
        @Override
        public void onShowPress(MotionEvent e) {
            System.out.println("被按住时...");     
        }
     
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            System.out.println("单击的时候离开屏幕");
            return false;
        }
     
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
                float distanceY) {
            System.out.println("滑动...");
            return true;
        }
     
        @Override
        public void onLongPress(MotionEvent e) {
            System.out.println("长按...");       
        }
     
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {
            System.out.println("极速滑动...");
            return true;
        }
     
    
    }
    

      总结:上面的demo是利用activity继承了OnGestureListener,OnDoubleTapListener两个接口,在activity里实现了这两个接口,GestureDetectorCompat mDetector在调用监听的事件,然后在activity里的onTouchEvent里调用mDetector的onTouch方法来调用处理监听到的事件(因此点击整个屏幕都可以响应)。若只想点击某一个控件里实现监听事件,则必须在一个控件里调用GestureDetectorCompat 的onTouch事件

    View myView = findViewById(R.id.my_view);   
        myView.setOnTouchListener(new OnTouchListener() {  
            public boolean onTouch(View v, MotionEvent event) {  
                // ... Respond to touch events         
                this.mDetector.onTouchEvent(event);  
                return onTouchEvent(event);  
            }  
        });  
    

      下面只在一个图文件里监听点击事件:记住覆写Ontouchlistener的onTouch方法,在该方法

    mDetector.onTouchEvent(event);
    return onTouchEvent(event);

    在哪View里调用就在哪个view里面才能监听到该事件。在activity里和一般的view里区别:一般的View在onTouch()里调用onTouchEvent()方法,而activity里直接覆写的onTouchEvent()方法里面返回时候,super.onTouchEvent。

    public class MainActivity extends Activity implements OnGestureListener,OnDoubleTapListener
    {
    	private GestureDetectorCompat mDetector; 
    	private ImageView im;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            im=(ImageView) findViewById(R.id.im);
            im.setOnTouchListener(new OnTouchListener() {
            	@Override
    			public boolean onTouch(View v, MotionEvent event) {
    
    				mDetector.onTouchEvent(event);
    				return onTouchEvent(event);
    			}
    		});
            mDetector=new GestureDetectorCompat(this,this); 
            mDetector.setOnDoubleTapListener(this);
        }
     
        
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
           system.out.println("单机事件完成");
            return true;
        }
      @Override public boolean onDoubleTap(MotionEvent e) { // TODO Auto-generated method stub System.out.println("双击了..."); return true; } @Override public boolean onDoubleTapEvent(MotionEvent e) { // Intent intent =new Intent(); // intent.setAction(Intent.ACTION_CALL); // intent.setData(Uri.parse("tel:"+15607209)); // startActivity(intent); System.out.println("双击事件完成..."); return true; } @Override public boolean onDown(MotionEvent e) { System.out.println("落下屏幕时候..."); return false; } @Override public void onShowPress(MotionEvent e) { System.out.println("被按住时..."); } @Override public boolean onSingleTapUp(MotionEvent e) { System.out.println("单击的时候离开屏幕"); return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { System.out.println("滑动..."); return true; } @Override public void onLongPress(MotionEvent e) { System.out.println("长按..."); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { System.out.println("极速滑动..."); return true; } }

      就是还有一个问题没解决:其它时间都正常,就是当我双击的时候,一次双击却执行了三次双击的意图,也就是说监听到了3次有时4次onDoubleTapEvent,猜测可能是双击事件完成后不断向activity的ontouch发送这个事件完成,直到onTouch处理后为止。因此在写双击的处理的事件的时候最好写在onDoubleTap方法里。而双击的时候第一次单机完成也会执行onSingleTapUp,因此点击单机事件的时候最好写在:onSingleTapConfirmed

     (3)利用SimpleOnGestureListener 只监听部分事件(原因上面已讲到):

    public class MainActivity extends Activity {   
          
        private GestureDetectorCompat mDetector;   
      
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
            mDetector = new GestureDetectorCompat(this, new MyGestureListener());  
        }  
      
        @Override   
        public boolean onTouchEvent(MotionEvent event){   
            this.mDetector.onTouchEvent(event);  
            return super.onTouchEvent(event);  
        }  
          
        class MyGestureListener extends GestureDetector.SimpleOnGestureListener {  
            private static final String DEBUG_TAG = "Gestures";   
              
            @Override  
            public boolean onDown(MotionEvent event) {   
                Log.d(DEBUG_TAG,"onDown: " + event.toString());   
                return true;  
            }  
      
            @Override  
            public boolean onFling(MotionEvent event1, MotionEvent event2,   
                    float velocityX, float velocityY) {  
                Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString());  
                return true;  
            }  
        }  
    }  
    

      PS:本文很多地方都参考了:http://blog.csdn.net/xyz_lmn/article/details/16826669

  • 相关阅读:
    java中的 equals 与 ==
    String类的内存分配
    SVN用命令行更换本地副本IP地址
    npoi 设置单元格格式
    net core 微服务框架 Viper 调用链路追踪
    打不死的小强 .net core 微服务 快速开发框架 Viper 限流
    net core 微服务 快速开发框架 Viper 初体验20201017
    Anno 框架 增加缓存、限流策略、事件总线、支持 thrift grpc 作为底层传输
    net core 微服务 快速开发框架
    Viper 微服务框架 编写一个hello world 插件02
  • 原文地址:https://www.cnblogs.com/bokeofzp/p/4756327.html
Copyright © 2011-2022 走看看