lmw
2024-05-21 0af0750101f969b6ff18d7ade37354b4bcdccd03
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package cn.sinata.xldutils.view.gesture;
 
import android.view.MotionEvent;
 
/**
 * Component that detects translation, scale and rotation based on touch events.
 * <p>
 * This class notifies its listeners whenever a gesture begins, updates or ends.
 * The instance of this detector is passed to the listeners, so it can be queried
 * for pivot, translation, scale or rotation.
 */
public class TransformGestureDetector implements MultiPointerGestureDetector.Listener {
 
  /** The listener for receiving notifications when gestures occur. */
  public interface Listener {
    /** Responds to the beginning of a gesture. */
    public void onGestureBegin(TransformGestureDetector detector);
 
    /** Responds to the update of a gesture in progress. */
    public void onGestureUpdate(TransformGestureDetector detector);
 
    /** Responds to the end of a gesture. */
    public void onGestureEnd(TransformGestureDetector detector);
  }
 
  private final MultiPointerGestureDetector mDetector;
 
  private Listener mListener = null;
 
  public TransformGestureDetector(MultiPointerGestureDetector multiPointerGestureDetector) {
    mDetector = multiPointerGestureDetector;
    mDetector.setListener(this);
  }
 
  /** Factory method that creates a new instance of TransformGestureDetector */
  public static TransformGestureDetector newInstance() {
    return new TransformGestureDetector(MultiPointerGestureDetector.newInstance());
  }
 
  /**
   * Sets the listener.
   * @param listener listener to set
   */
  public void setListener(Listener listener) {
    mListener = listener;
  }
 
  /**
   * Resets the component to the initial state.
   */
  public void reset() {
    mDetector.reset();
  }
 
  /**
   * Handles the given motion event.
   * @param event event to handle
   * @return whether or not the event was handled
   */
  public boolean onTouchEvent(final MotionEvent event) {
    return mDetector.onTouchEvent(event);
  }
 
  @Override
  public void onGestureBegin(MultiPointerGestureDetector detector) {
    if (mListener != null) {
      mListener.onGestureBegin(this);
    }
  }
 
  @Override
  public void onGestureUpdate(MultiPointerGestureDetector detector) {
    if (mListener != null) {
      mListener.onGestureUpdate(this);
    }
  }
 
  @Override
  public void onGestureEnd(MultiPointerGestureDetector detector) {
    if (mListener != null) {
      mListener.onGestureEnd(this);
    }
  }
 
  private float calcAverage(float[] arr, int len) {
    float sum = 0;
    for (int i = 0; i < len; i++) {
      sum += arr[i];
    }
    return (len > 0) ? sum / len : 0;
  }
 
  /** Restarts the current gesture */
  public void restartGesture() {
    mDetector.restartGesture();
  }
 
  /** Gets whether gesture is in progress or not */
  public boolean isGestureInProgress() {
    return mDetector.isGestureInProgress();
  }
 
  /** Gets the X coordinate of the pivot point */
  public float getPivotX() {
    return calcAverage(mDetector.getStartX(), mDetector.getCount());
  }
 
  /** Gets the Y coordinate of the pivot point */
  public float getPivotY() {
    return calcAverage(mDetector.getStartY(), mDetector.getCount());
  }
 
  /** Gets the X component of the translation */
  public float getTranslationX() {
    return calcAverage(mDetector.getCurrentX(), mDetector.getCount()) -
        calcAverage(mDetector.getStartX(), mDetector.getCount());
  }
 
  /** Gets the Y component of the translation */
  public float getTranslationY() {
    return calcAverage(mDetector.getCurrentY(), mDetector.getCount()) -
        calcAverage(mDetector.getStartY(), mDetector.getCount());
  }
 
  /** Gets the scale */
  public float getScale() {
    if (mDetector.getCount() < 2) {
      return 1;
    } else {
      float startDeltaX = mDetector.getStartX()[1] - mDetector.getStartX()[0];
      float startDeltaY = mDetector.getStartY()[1] - mDetector.getStartY()[0];
      float currentDeltaX = mDetector.getCurrentX()[1] - mDetector.getCurrentX()[0];
      float currentDeltaY = mDetector.getCurrentY()[1] - mDetector.getCurrentY()[0];
      float startDist = (float) Math.hypot(startDeltaX, startDeltaY);
      float currentDist = (float) Math.hypot(currentDeltaX, currentDeltaY);
      return currentDist / startDist;
    }
  }
 
  /** Gets the rotation in radians */
  public float getRotation() {
    if (mDetector.getCount() < 2) {
      return 0;
    } else {
      float startDeltaX = mDetector.getStartX()[1] - mDetector.getStartX()[0];
      float startDeltaY = mDetector.getStartY()[1] - mDetector.getStartY()[0];
      float currentDeltaX = mDetector.getCurrentX()[1] - mDetector.getCurrentX()[0];
      float currentDeltaY = mDetector.getCurrentY()[1] - mDetector.getCurrentY()[0];
      float startAngle = (float) Math.atan2(startDeltaY, startDeltaX);
      float currentAngle = (float) Math.atan2(currentDeltaY, currentDeltaX);
      return currentAngle - startAngle;
    }
  }
}