手势识别官方教程(7)识别缩放手势用ScaleGestureDetector和SimpleOnScaleGestureListener

1.Use Touch to Perform Scaling

  As discussed in Detecting Common GesturesGestureDetector helps you detect common gestures used by Android such as scrollingflinging, and long press. For scaling, Android provides ScaleGestureDetector .   GestureDetector and ScaleGestureDetector can be used together when you want a view to recognize additional gestures.

  ScaleGestureDetector 是用来识别缩放手势的。它可以和GestureDetector同时使用,来识别额外的手势.

  To report detected gesture events, gesture detectors use listener objects passed to their constructors.ScaleGestureDetector uses ScaleGestureDetector.OnScaleGestureListener. Android provides ScaleGestureDetector.SimpleOnScaleGestureListener as a helper class that you can extend if you don’t care about all of the reported events.

  ScaleGestureDetector.SimpleOnScaleGestureListener 是一个封装好的缩放手势类.用来接收探测到的手势,构造手势探测器 ScaleGestureDetector 的时候要用到它.

2.Basic scaling example

  Here is a snippet that illustrates the basic ingredients involved in scaling.

复制代码
 1 private ScaleGestureDetector mScaleDetector;
 2 private float mScaleFactor = 1.f;
 3 
 4 public MyCustomView(Context mContext){
 5     ...
 6     // View code goes here
 7     ...
 8     mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
 9 }
10 
11 @Override
12 public boolean onTouchEvent(MotionEvent ev) {
13     // Let the ScaleGestureDetector inspect all events.
14     mScaleDetector.onTouchEvent(ev);
15     return true;
16 }
17 
18 @Override
19 public void onDraw(Canvas canvas) {
20     super.onDraw(canvas);
21 
22     canvas.save();
23     canvas.scale(mScaleFactor, mScaleFactor);
24     ...
25     // onDraw() code goes here
26     ...
27     canvas.restore();
28 }
29 
30 private class ScaleListener 
31         extends ScaleGestureDetector.SimpleOnScaleGestureListener {
32     @Override
33     public boolean onScale(ScaleGestureDetector detector) {
34         mScaleFactor *= detector.getScaleFactor();
35 
36         // Don't let the object get too small or too large.
37         mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
38 
39         invalidate();
40         return true;
41     }
42 }
复制代码

3.More complex scaling example

  Here is a more complex example from the InteractiveChart sample provided with this class. TheInteractiveChart sample supports both scrolling (panning) and scaling with multiple fingers, using the ScaleGestureDetector "span" (getCurrentSpanX/Y) and "focus" (getFocusX/Y) features:

  下面是一个复杂的手势识别示例的片段,使用了两个识别器.完整示例下载地址 InteractiveChart
复制代码
 1 @Override
 2 private RectF mCurrentViewport = 
 3         new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX);
 4 private Rect mContentRect;
 5 private ScaleGestureDetector mScaleGestureDetector;
 6 ...
 7 public boolean onTouchEvent(MotionEvent event) {
 8     boolean retVal = mScaleGestureDetector.onTouchEvent(event);
 9     retVal = mGestureDetector.onTouchEvent(event) || retVal;
10     return retVal || super.onTouchEvent(event);
11 }
12 
13 /**
14  * The scale listener, used for handling multi-finger scale gestures.
15  */
16 private final ScaleGestureDetector.OnScaleGestureListener mScaleGestureListener
17         = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
18     /**
19      * This is the active focal point in terms of the viewport. Could be a local
20      * variable but kept here to minimize per-frame allocations.
21      */
22     private PointF viewportFocus = new PointF();
23     private float lastSpanX;
24     private float lastSpanY;
25 
26     // Detects that new pointers are going down.
27     @Override
28     public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
29         lastSpanX = ScaleGestureDetectorCompat.
30                 getCurrentSpanX(scaleGestureDetector);
31         lastSpanY = ScaleGestureDetectorCompat.
32                 getCurrentSpanY(scaleGestureDetector);
33         return true;
34     }
35 
36     @Override
37     public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
38 
39         float spanX = ScaleGestureDetectorCompat.
40                 getCurrentSpanX(scaleGestureDetector);
41         float spanY = ScaleGestureDetectorCompat.
42                 getCurrentSpanY(scaleGestureDetector);
43 
44         float newWidth = lastSpanX / spanX * mCurrentViewport.width();
45         float newHeight = lastSpanY / spanY * mCurrentViewport.height();
46 
47         float focusX = scaleGestureDetector.getFocusX();
48         float focusY = scaleGestureDetector.getFocusY();
49         // Makes sure that the chart point is within the chart region.
50         // See the sample for the implementation of hitTest().
51         hitTest(scaleGestureDetector.getFocusX(),
52                 scaleGestureDetector.getFocusY(),
53                 viewportFocus);
54 
55         mCurrentViewport.set(
56                 viewportFocus.x
57                         - newWidth * (focusX - mContentRect.left)
58                         / mContentRect.width(),
59                 viewportFocus.y
60                         - newHeight * (mContentRect.bottom - focusY)
61                         / mContentRect.height(),
62                 0,
63                 0);
64         mCurrentViewport.right = mCurrentViewport.left + newWidth;
65         mCurrentViewport.bottom = mCurrentViewport.top + newHeight;     
66         ...
67         // Invalidates the View to update the display.
68         ViewCompat.postInvalidateOnAnimation(InteractiveLineGraphView.this);
69 
70         lastSpanX = spanX;
71         lastSpanY = spanY;
72         return true;
73     }
74 };
复制代码

 

posted @   f9q  阅读(1678)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示