Android development Android gestures

The previous app did not have any gesture support at all. For the current program, if there is no support for some gestures, it feels a bit behind. App that supports gestures is called cool. So while rebuilding the ifood for android framework this time, I was determined to make my App fully support gestures. Let's take a look at an example of a global sliding switch window implemented by myself.

In the android system, gesture recognition is achieved through the GestureDetector.OnGestureListener interface. If you want to customize gestures, you need to rewrite some of the methods in this interface, not much nonsense, the following code:

A custom GestureLisntener:

MyGestureListener.java
public class MyGestureListener implements OnGestureListener {
     
     

	static final String TAG = "MyGestureListener";

	private static final int SWIPE_MAX_OFF_PATH = 100;
	private static final int SWIPE_MIN_DISTANCE = 100;
	private static final int SWIPE_THRESHOLD_VELOCITY = 100;
	
	public Context context;
	
	public MyGestureListener(Context context) {
     
     
		this.context = context;
	}

	@Override
	public boolean onDown(MotionEvent e) {
     
     
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onShowPress(MotionEvent e) {
     
     
		// TODO Auto-generated method stub
		Log.e(TAG, "onShowPress");
	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
     
     
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
     
     
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onLongPress(MotionEvent e) {
     
     
		// TODO Auto-generated method stub
		Log.e(TAG, "onLongPress");
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
     
     
		if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
			return false;

		if ((e1.getX() - e2.getX()) > SWIPE_MIN_DISTANCE
				&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
     
     
			Log.e(TAG, "onFling left");

		} else if ((e2.getX() - e1.getX()) > SWIPE_MIN_DISTANCE
				&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
     
     
			Log.e(TAG, "onFling right");
			((Activity) context).finish();
			
		}
		return true;
	}

}

In the onFling() method in this class, the interface is switched when sliding from left to right. If there is more complex gesture support, you can also add it in this base class.

Next, create a new GestureActivity to implement the Gesture sliding switch interface, and let the gesture-supporting Activity inherit it, so that it inherits its gesture support function and improves code reuse.

GestureActivity.java
public class GestureActivity extends ActivityBase {
     
     

	MyGestureListener listener = new MyGestureListener(this);
	protected GestureDetector gestureDetector = new GestureDetector(listener);
	
	public boolean onTouchEvent(MotionEvent event) {
     
     
        if (gestureDetector.onTouchEvent(event))
            return true;
        else  
            return false;
    }
	
}

In this way, a simple sliding and switching page framework is realized. If you want to support more gestures, you only need to rewrite the MyGestureListener method.

But don't be happy too early. In general Activity gesture support is normal, but when you encounter some Activities that contain ScrollView or ListView, the gestures will not respond. The reason is that these sliding components already have gesture support, which will cause conflicts, resulting in custom gestures that are not recognized. I googled for a long time, and it seems that there is no specific method. Later I saw that the dispatchTouchEvent (MotionEvent ev) method was used, and it really worked. So there is such a method in GestureActivity:

public boolean dispatchTouchEvent(MotionEvent ev) {
     
     
    gestureDetector.onTouchEvent(ev);
    return super.dispatchTouchEvent(ev);
}

Try again at this time, and sure enough all Activities have implemented custom gesture events. But why this method is enough? It must be understood.

The event types in android are divided into key events and screen touch events. Touch events are the basic events of screen touch events, and it is necessary to have an in-depth understanding of them.

一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE…->ACTION_MOVE->ACTION_UP

当屏幕中包含一个ViewGroup,而这个ViewGroup又包含一个子view,这个时候android系统如何处理Touch事件呢?到底是ViewGroup来处理Touch事件,还是子view来处理Touch事件呢?答案是:不一定。

android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法:

1.public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent

2.public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent

3.public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent

当TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的 dispatchTouchEvent ,然后由 dispatchTouchEvent 方法进行分发,如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。如果事件传递到某一层的子 view 的 onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是 onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。

看到这终于清楚了上面的疑问,dispatchTouchEvent()方法直接将触摸事件交给了gestureDetector的触摸事件,这样就解决了冲突问题。

Guess you like

Origin blog.csdn.net/xhf_123/article/details/49934987