手势识别官方教程(6)识别拖拽手势用GestureDetector.SimpleOnGestureListener和onTouchEvent
三种现实drag方式
1,在3.0以后可以直接用 View.OnDragListener (在onTouchEvent中调用某个view的startDrag())
2,onTouchEvent()
3,GestureDetector.SimpleOnGestureListener 的onScroll
Dragging
This lesson describes how to use touch gestures to drag, using onTouchEvent() to intercept touch events.
1.Drag an Object
If you are targeting Android 3.0 or higher, you can use the built-in drag-and-drop event listeners with View.OnDragListener, as described in Drag and Drop.
A common operation for a touch gesture is to use it to drag an object across the screen. The following snippet lets the user drag an on-screen image. Note the following:
- In a drag (or scroll) operation, the app has to keep track of the original pointer (finger), even if additional fingers get placed on the screen. For example, imagine that while dragging the image around, the user places a second finger on the touch screen and lifts the first finger. If your app is just tracking individual pointers, it will regard the second pointer as the default and move the image to that location.
拖拽和滚动手势时,要支持手指交换移动或拖拽,以拖图片为例,当第二个手指按图片且第一个手指离开后,第二个手指应仍然可以拖拽。
- To prevent this from happening, your app needs to distinguish between the original pointer and any follow-on pointers. To do this, it tracks the
ACTION_POINTER_DOWNandACTION_POINTER_UPevents described in Handling Multi-Touch Gestures.ACTION_POINTER_DOWNandACTION_POINTER_UPare passed to theonTouchEvent()callback whenever a secondary pointer goes down or up.为了实现第一条,应该注意原始手指和后续手指。
- In the
ACTION_POINTER_UPcase, the example extracts this index and ensures that the active pointer ID is not referring to a pointer that is no longer touching the screen. If it is, the app selects a different pointer to be active and saves its current X and Y position. Since this saved position is used in theACTION_MOVEcase to calculate the distance to move the onscreen object, the app will always calculate the distance to move using data from the correct pointer.
The following snippet enables a user to drag an object around on the screen. It records the initial position of the active pointer, calculates the distance the pointer traveled, and moves the object to the new position. It correctly manages the possibility of additional pointers, as described above.
Notice that the snippet uses the getActionMasked() method. You should always use this method (or better yet, the compatability version MotionEventCompat.getActionMasked()) to retrieve the action of a MotionEvent. Unlike the older getAction() method, getActionMasked() is designed to work with multiple pointers. It returns the masked action being performed, without including the pointer index bits.
用 getActionMasked() 而不用 getAction(),前者支持多点触摸。
在屏幕上拖拽一个目标的示例
// The ‘active pointer’ is the one currently moving our object.
private int mActivePointerId = INVALID_POINTER_ID; @Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev); final int action = MotionEventCompat.getActionMasked(ev); switch (action) {
case MotionEvent.ACTION_DOWN: {
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex); // Remember where we started (for dragging)
mLastTouchX = x;
mLastTouchY = y;
// Save the ID of this pointer (for dragging)
mActivePointerId = MotionEventCompat.getPointerId(ev, );
break;
} case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
final int pointerIndex =
MotionEventCompat.findPointerIndex(ev, mActivePointerId); final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex); // Calculate the distance moved
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY; mPosX += dx;
mPosY += dy; invalidate(); // Remember this touch position for the next move event
mLastTouchX = x;
mLastTouchY = y; break;
} case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
} case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
} case MotionEvent.ACTION_POINTER_UP: { final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == ? : ;
mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);
mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);
mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
}
break;
}
}
return true;
}
2.Drag to Pan(拖到托盘上)
The previous section showed an example of dragging an object around the screen. Another common scenario is panning, which is when a user's dragging motion causes scrolling in both the x and y axes. The above snippet directly intercepted the MotionEvent actions to implement dragging. The snippet in this section takes advantage of the platform's built-in support for common gestures. It overrides onScroll() in GestureDetector.SimpleOnGestureListener.
To provide a little more context, onScroll() is called when a user is dragging his finger to pan the content. onScroll() is only called when a finger is down; as soon as the finger is lifted from the screen, the gesture either ends, or a fling gesture is started (if the finger was moving with some speed just before it was lifted). For more discussion of scrolling vs. flinging, see Animating a Scroll Gesture.
Here is the snippet for onScroll():
// The current viewport. This rectangle represents the currently visible
// chart domain and range.
private RectF mCurrentViewport =
new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX); // The current destination rectangle (in pixel coordinates) into which the
// chart data should be drawn.
private Rect mContentRect; private final GestureDetector.SimpleOnGestureListener mGestureListener
= new GestureDetector.SimpleOnGestureListener() {
... @Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// Scrolling uses math based on the viewport (as opposed to math using pixels). // Pixel offset is the offset in screen pixels, while viewport offset is the
// offset within the current viewport.
float viewportOffsetX = distanceX * mCurrentViewport.width()
/ mContentRect.width();
float viewportOffsetY = -distanceY * mCurrentViewport.height()
/ mContentRect.height();
...
// Updates the viewport, refreshes the display.
setViewportBottomLeft(
mCurrentViewport.left + viewportOffsetX,
mCurrentViewport.bottom + viewportOffsetY);
...
return true;
}
The implementation of onScroll() scrolls the viewport in response to the touch gesture:
/**
* Sets the current viewport (defined by mCurrentViewport) to the given
* X and Y positions. Note that the Y value represents the topmost pixel position,
* and thus the bottom of the mCurrentViewport rectangle.
*/
private void setViewportBottomLeft(float x, float y) {
/*
* Constrains within the scroll range. The scroll range is simply the viewport
* extremes (AXIS_X_MAX, etc.) minus the viewport size. For example, if the
* extremes were 0 and 10, and the viewport size was 2, the scroll range would
* be 0 to 8.
*/ float curWidth = mCurrentViewport.width();
float curHeight = mCurrentViewport.height();
x = Math.max(AXIS_X_MIN, Math.min(x, AXIS_X_MAX - curWidth));
y = Math.max(AXIS_Y_MIN + curHeight, Math.min(y, AXIS_Y_MAX)); mCurrentViewport.set(x, y - curHeight, x + curWidth, y); // Invalidates the View to update the display.
ViewCompat.postInvalidateOnAnimation(this);
}
手势识别官方教程(6)识别拖拽手势用GestureDetector.SimpleOnGestureListener和onTouchEvent的更多相关文章
- 手势识别官方教程(2)识别常见手势用GestureDetector+手势回调接口/手势抽象类
简介 GestureDetector识别手势. GestureDetector.OnGestureListener是识别手势后的回调接口.GestureDetector.SimpleOnGesture ...
- 手势识别官方教程(7)识别缩放手势用ScaleGestureDetector.GestureDetector和ScaleGestureDetector.SimpleOnScaleGestureListener
Use Touch to Perform Scaling As discussed in Detecting Common Gestures, GestureDetector helps you de ...
- 手势识别官方教程(7)识别缩放手势用ScaleGestureDetector和SimpleOnScaleGestureListener
1.Use Touch to Perform Scaling As discussed in Detecting Common Gestures, GestureDetector helps you ...
- 手势识别官方教程(3)识别移动手势(识别速度用VelocityTracker)
moving手势在onTouchEvent()或onTouch()中就可识别,编程时主要是识别积云的速度用VelocityTracker等, Tracking Movement This lesson ...
- 手势识别官方教程(4)在挑划或拖动手势后view的滚动用ScrollView和 HorizontalScrollView,自定义用Scroller或OverScroller
简单滚动用ScrollView和 HorizontalScrollView就够.自定义view时可能要自定义滚动效果,可以使用 Scroller或 OverScroller Animating a S ...
- 手势识别官方教程(8)拦截触摸事件,得到触摸的属性如速度,距离等,控制view展开
onInterceptTouchEvent可在onTouchEvent()前拦截触摸事件, ViewConfiguration得到触摸的属性如速度,距离等, TouchDelegate控制view展开 ...
- Blend4精选案例图解教程(三):一键拖拽
原文:Blend4精选案例图解教程(三):一键拖拽 拖拽效果,常规实现方法是定义MoveLeftDwon.MoveLeftUp.MouseMove事件,在Blend的世界里,实现对象的拖拽,可以不写一 ...
- 关于PC端与手机端随着手指移动图片位置放生变化的拖拽事件
当按下鼠标时,图片随鼠标移动松开时图片回到原位 drag("div_id") function drag(node_id){ var node = document.getElem ...
- android银行卡匹配、详情展开动画、仿爱奇艺视频拖拽、扫码识别手机号等源码
Android精选源码 android实现银行卡匹配信息源码 android实现可以展开查看详情的卡片 下拉刷新,上拉加载,侧滑显示菜单等效果RefreshSwipeRecyclerview andr ...
随机推荐
- <转载>国外程序员推荐的免费编程书籍资源
一.George Stocker 提供了一大串,分类如下: How to Design Programs: An Introduction to Computing and Programming 2 ...
- SSH连接时出现「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」解决办法
用ssh來操控github,沒想到連線時,出現「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」,後面還有一大串英文,這時當然要向Google大神求助 ...
- English Audio-Books
Downloadble English Audio-Books websites 一.网站 1.可听书 2.山寨 3.有声书库 4.audioboom.com 5.豆瓣小站 6.AudioBook 二 ...
- Arithmetic Expression
时间限制:2000ms 单点时限:200ms 内存限制:256MB 描述 Given N arithmetic expressions, can you tell whose result is cl ...
- PLINQ 简介
PLINQ和LINQ的语法基本是差不多的,PLINQ该如何实现并行 var query = from item in source.AsParallel() select item; 一个简单的AsP ...
- opensuse安装mysql-workbench
首先安装好mysqlserver,做本地测试其实不用安装mysqlclient. 到http://software.opensuse.org/package/mysql-workbench 下载相应版 ...
- 图片裁切插件jCrop的使用心得(一)
之前,项目经理为了提升用户体验让我在之前图片上传功能的基础上实现图片的裁切功能,作为一个前端小白来说听了这个需求心里一紧,毕竟没有做过,于是跟项目经理商量要先做下调研.在一上午的调研中发现了jCrop ...
- 如何更改Chrome默认的搜索引擎
1 打开Chrome浏览器之后,点击窗口右上角的图标,在弹出的菜单中点击设置,如图所示: 2 在打开的窗口中,点击管理搜索引擎,如下图所示: 3 在弹出的窗口中,找到百度的搜索引擎或者bing的搜索 ...
- php设计模式-------(1)策略模式
一.为什么我要学习设计模式. 我的上一个项目是做App接口,由于时间紧,老板催的急,所以到最后项目完工时发现居然写了几万行代码,可想而知代码质量有多糟糕.而且很多时候,调用接口的开发人员来找我说某个接 ...
- 设置nginx禁止通过IP访问服务器的方法
在Nginx上设置禁止通过IP访问服务器,只允许通过域名访问,以避免别人把未备案的域名解析到自己的服务器IP而导致服务器被断网. nginx的默认虚拟主机允许用户通过IP访问,或者通过未设置的域名访问 ...