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 };

 

相关文章: