手势识别官方教程(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 @ 2015-10-08 18:06  f9q  阅读(1663)  评论(0编辑  收藏  举报