Android 手势—— GestureDetector 和 SimpleOnScaleGestureListener (手势缩放)
GestureDetector 的作用:
檢測各種手勢和事件,使用的使用一般和onTouchEvent 方法結(jié)合在一起使用
下面主要說的內(nèi)容是GestureDetector 和?ScaleGestureDetector
1?GestureDetector
里面有一些回調(diào)接口下面說下
1.1?OnGestureListener 這個是接口,實(shí)現(xiàn)的時候里面的方法會自動生成,
1.2?SimpleOnGestureListener 這個是靜態(tài)的里面的方法需要自己重寫,就是有時候不需要讓生成一大堆的方法,可以使用
這個(平時開發(fā)可是使用SimpleOnGestureListener基本滿足打說需求)
1.3?OnDoubleTapListener 這個是接口里面3個方法SimpleOnGestureListener都有,所以這個就不說了,
1.4?OnContextClickListener 這個也是接口里面有1個方法SimpleOnGestureListener都有,所以這個就不說了,
所以建議大家項(xiàng)目開發(fā)中使用SimpleOnGestureListener 包含了其他的三個的所有方法,需要的時候重寫一些方法即可,下面
下2個demo 僅供參考
OnGestureListener 這個是接口,實(shí)現(xiàn)的時候里面的方法會自動生成,
(1)boolean onDown(MotionEvent e);// 按下事件
(2)public void onShowPress(MotionEvent e)? //用戶已執(zhí)行down{@link MotionEvent}但未執(zhí)行 一個移動或上升。此事件通常用于提供 反饋給用戶,讓他們知道他們的行為 識別,即突出顯示一個元素
(3)public boolean onSingleTapUp(MotionEvent e) //?在按下并抬起時發(fā)生, 使用up{@link MotionEvent}進(jìn)行點(diǎn)擊時通 ?觸發(fā)了它。 @param e完成第一次點(diǎn)擊的向上運(yùn)動事件 @如果事件被消耗,則返回true,否則返回false
(4)public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) //?在屏幕上滑動 ?@param e1開始滾動的第一個向下運(yùn)動事件。 ?@param e2觸發(fā)當(dāng)前onScroll的移動動作事件。?@param distanceX自上一次滾動以來沿X軸的距離??onScroll。這不是{@code e1}之間的距離和{@code e2}。 ?@param distance自上一次滾動以來沿Y軸的距 *onScroll。這不是{@code e1}之間的距離和{@code e2}。 @return true如果事件被消耗,否則為false
(5)onLongPress? // 長按事件
(6)onFling? //? 按下觸摸屏、快速移動后松開 @param e1開始投擲的第一個向下運(yùn)動事件。 @param e2觸發(fā)當(dāng)前觸發(fā)的移動動作事件。 @param velocityX這個投擲的速度,以像素每秒為單位 沿x軸。 @param velocityY這個投擲的速度,以像素每秒為單位 沿y軸。 @return true如果事件被消耗,否則為false
下面開始寫一個demo 看看GestureDetector ,寫一個點(diǎn)擊的時候圖片移動到點(diǎn)擊的位置
下面看下代碼:?
public class TestView extends View {// paint 初始化private Paint paint;private Bitmap bitmap;private int mPointX;private int mPointY;private static String TAG = "---------gestureDetector";public TestView(Context context) {super(context);}public TestView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context, attrs);}public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}private void init(Context context, AttributeSet attrs) {paint = new Paint();
// paint.setColor(Color.RED);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.girl);canvas.drawBitmap(bitmap, mPointX, mPointY, paint);}@Overridepublic boolean onTouchEvent(MotionEvent event) {return gestureDetector.onTouchEvent(event);}GestureDetector gestureDetector = new GestureDetector(getContext(),new GestureDetector.OnGestureListener() {// 按下@Overridepublic boolean onDown(MotionEvent e) {Log.e(TAG, "onDown");mPointX = (int) e.getX();mPointY = (int) e.getY();invalidate();return false;}/**用戶已執(zhí)行down{@link MotionEvent}但未執(zhí)行一個移動或上升。此事件通常用于提供反饋給用戶,讓他們知道他們的行為識別,即突出顯示一個元素**/@Overridepublic void onShowPress(MotionEvent e) {Log.e(TAG, "onShowPress");}/*** 使用up{@link MotionEvent}進(jìn)行點(diǎn)擊時通* 觸發(fā)了它。* @param e完成第一次點(diǎn)擊的向上運(yùn)動事件* @如果事件被消耗,則返回true,否則返回false* @param e* @return*/@Overridepublic boolean onSingleTapUp(MotionEvent e) {Log.e(TAG, "onSingleTapUp");return false;}/*** 在屏幕上滑動* @param e1開始滾動的第一個向下運(yùn)動事件。* @param e2觸發(fā)當(dāng)前onScroll的移動動作事件。* @param distanceX自上一次滾動以來沿X軸的距離* onScroll。這不是{@code e1}之間的距離和{@code e2}。* @param distance自上一次滾動以來沿Y軸的距* onScroll。這不是{@code e1}之間的距離和{@code e2}。* *@return true如果事件被消耗,否則為false* @param e1* @param e2* @param distanceX* @param distanceY* @return*/@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY) {Log.e(TAG, "onScroll");return false;}// 長按@Overridepublic void onLongPress(MotionEvent e) {Log.e(TAG, "onLongPress");}/*** 按下觸摸屏、快速移動后松開* *@param e1開始投擲的第一個向下運(yùn)動事件。* *@param e2觸發(fā)當(dāng)前觸發(fā)的移動動作事件。* *@param velocityX這個投擲的速度,以像素每秒為單位* *沿x軸。* *@param velocityY這個投擲的速度,以像素每秒為單位* *沿y軸。* *@return true如果事件被消耗,否則為false* @param e1* @param e2* @param velocityX* @param velocityY* @return*/@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {Log.e(TAG, "onFling");return false;}});}
可能有人說使用onTouchEvent 就可以實(shí)現(xiàn)了,這里只是簡單的熟悉GestureDetector使用,
1.2? ?SimpleOnGestureListener 這個是靜態(tài)的里面的方法需要自己重寫,就是有時候不需要讓生成一大堆的方法,可以使用
這個 但是里面多了幾個方法
(1)onSingleTapConfirmed? :這個回顧下onSingleTapUp?在按下并抬起時發(fā)生,onSingleTapConfirmed是?在按下并抬起時發(fā)生但是多了個附加條件就是會確保單擊之后短時間內(nèi)沒有再次單擊,
(2)onDoubleTap:雙擊的第二下Touch down時觸發(fā)
(3)onDoubleTapEvent:雙擊的第二下Touch down和up都會觸發(fā)
其他的事件基本一樣
下面使用SimpleOnGestureListener 寫一個寫一個點(diǎn)擊圖片放大的效果
public class TestView extends View {// paint 初始化private Paint paint;private Bitmap bitmap;private Matrix matrix = new Matrix();private static String TAG = "---------gestureDetector";public TestView(Context context) {super(context);}public TestView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context, attrs);}public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}private void init(Context context, AttributeSet attrs) {paint = new Paint();// paint.setColor(Color.RED);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.girl);canvas.drawBitmap(bitmap, matrix, paint);}@Overridepublic boolean onTouchEvent(MotionEvent event) {return gestureDetector.onTouchEvent(event);}GestureDetector gestureDetector = new GestureDetector(getContext(),new GestureDetector.SimpleOnGestureListener() {@Overridepublic boolean onDown(MotionEvent e) {matrix.postScale(1.5f, 1.5f);invalidate();return super.onDown(e);}});}
?2?ScaleGestureDetector 手勢的縮放
使用方法和GestureDetector 差不多,
里面的接口回調(diào)方法如下
2.1??OnScaleGestureListener 是接口使用的時候回自動生成3個方法
(1)onScale 縮放進(jìn)行中
(2)onScaleBegin 縮放開始
(3)onScaleEnd 縮放結(jié)束
2.2?SimpleOnScaleGestureListener 這個是靜態(tài)的類 的三個方法和OnScaleGestureListener 一樣,不過用到的時候需要重寫一下
下面是一個demo 實(shí)現(xiàn)圖片的縮放,效果出現(xiàn)了邊界,沒有限制,這里只是演示OnScaleGestureListener 使用,實(shí)現(xiàn)圖片可以縮放了,
public class TestView extends View {// paint 初始化private Paint paint;private Bitmap bitmap;private float scaleX;private float scaleY;Matrix matrix = new Matrix();private static String TAG = "---------gestureDetector";public TestView(Context context) {super(context);}public TestView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init(context, attrs);}public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}private void init(Context context, AttributeSet attrs) {paint = new Paint();// paint.setColor(Color.RED);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.girl);canvas.drawBitmap(bitmap, matrix, paint);}float[] m = new float[9];private float getMatrixScaleY() {matrix.getValues(m);return m[4];}@Overridepublic boolean onTouchEvent(MotionEvent event) {return scaleGestureDetector.onTouchEvent(event);}ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(getContext(),new ScaleGestureDetector.OnScaleGestureListener() {@Overridepublic boolean onScale(ScaleGestureDetector detector) {float scaleFactor = detector.getScaleFactor();Log.e("--------onScale", String.valueOf(scaleFactor));scaleX = detector.getCurrentSpanX();scaleY = detector.getCurrentSpanY();Log.e("--------scaleX", String.valueOf(scaleX));Log.e("--------scaleY", String.valueOf(scaleY));if (getMatrixScaleY() * scaleFactor > 2) {scaleFactor = 2 / getMatrixScaleY();}if (getMatrixScaleY() * scaleFactor < 0.5) {scaleFactor = 0.5f / getMatrixScaleY();}matrix.postScale(scaleFactor, scaleFactor, scaleX, scaleY);invalidate();return true;}@Overridepublic boolean onScaleBegin(ScaleGestureDetector detector) {Log.e("--------onScaleBegin", String.valueOf(detector.getScaleFactor()));return true;}@Overridepublic void onScaleEnd(ScaleGestureDetector detector) {Log.e("--------onScaleEnd", String.valueOf(detector.getScaleFactor()));}});}
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的Android 手势—— GestureDetector 和 SimpleOnScaleGestureListener (手势缩放)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有多少钱才能玩得起福特F150猛禽
- 下一篇: 总成本包括折旧费用吗?