我试图使用这样的代码用两根手指拖动来滚动(平移)一个对象:
anim = ObjectAnimator.ofInt(mJotView, "Top", newTop);
anim.setDuration(10);
anim.start();
但是,由于这些代码被多次调用,当用户用两根手指拖动时,它实际上什么都不做,只是滚动几个像素。
我错过了什么?
答案 0 :(得分:1)
尝试将此实现用于OnTouchLisnener
private class MultiTouchListener implements View.OnTouchListener {
private static final int INVALID_POINTER_ID = -1;
public boolean isRotateEnabled = true;
public boolean isTranslateEnabled = true;
public boolean isScaleEnabled = true;
public float minimumScale = 0.5f;
public float maximumScale = 10.0f;
private int mActivePointerId = INVALID_POINTER_ID;
private float mPrevX;
private float mPrevY;
private float scale = 1;
private ScaleGestureDetector mScaleGestureDetector;
private long startClickTime;
MultiTouchListener(float minimumScale, float maximumScale, float startScale) {
this.minimumScale = minimumScale;
this.maximumScale = maximumScale;
this.scale = startScale;
mScaleGestureDetector = new ScaleGestureDetector(new ScaleGestureListener());
}
private float adjustAngle(float degrees) {
if (degrees > 180.0f) {
degrees -= 360.0f;
} else if (degrees < -180.0f) {
degrees += 360.0f;
}
return degrees;
}
private void move(View view, TransformInfo info) {
computeRenderOffset(view, info.pivotX, info.pivotY);
adjustTranslation(view, info.deltaX, info.deltaY);
// Assume that scaling still maintains aspect ratio.
float scale = view.getScaleX() * info.deltaScale;
scale = Math.max(info.minimumScale, Math.min(info.maximumScale, scale));
this.scale = scale;
view.setScaleX(scale);
view.setScaleY(scale);
float rotation = adjustAngle(view.getRotation() + info.deltaAngle);
FloatingActionMenu.this.rotation = rotation;
view.setRotation(rotation);
}
private void adjustTranslation(View view, float deltaX, float deltaY) {
float[] deltaVector = {deltaX, deltaY};
view.getMatrix().mapVectors(deltaVector);
view.setTranslationX(view.getTranslationX() + deltaVector[0]);
view.setTranslationY(view.getTranslationY() + deltaVector[1]);
}
private void computeRenderOffset(View view, float pivotX, float pivotY) {
if (view.getPivotX() == pivotX && view.getPivotY() == pivotY) {
return;
}
float[] prevPoint = {0.0f, 0.0f};
view.getMatrix().mapPoints(prevPoint);
view.setPivotX(pivotX);
view.setPivotY(pivotY);
float[] currPoint = {0.0f, 0.0f};
view.getMatrix().mapPoints(currPoint);
float offsetX = currPoint[0] - prevPoint[0];
float offsetY = currPoint[1] - prevPoint[1];
view.setTranslationX(view.getTranslationX() - offsetX);
view.setTranslationY(view.getTranslationY() - offsetY);
}
@Override
public boolean onTouch(View view, MotionEvent event) {
mScaleGestureDetector.onTouchEvent(view, event);
if (!isTranslateEnabled) {
return true;
}
int action = event.getAction();
switch (action & event.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
mPrevX = event.getX();
mPrevY = event.getY();
// Save the ID of this pointer.
mActivePointerId = event.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position.
int pointerIndex = event.findPointerIndex(mActivePointerId);
if (pointerIndex != -1) {
// Only move if the ScaleGestureDetector isn't processing a
// gesture.
if (!mScaleGestureDetector.isInProgress()) {
adjustTranslation(view, currX - mPrevX, currY - mPrevY);
}
}
break;
}
case MotionEvent.ACTION_CANCEL:
mActivePointerId = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_UP:
mActivePointerId = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP: {
// Extract the index of the pointer that left the touch sensor.
int pointerIndex =
(action & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mPrevX = event.getX(newPointerIndex);
mPrevY = event.getY(newPointerIndex);
mActivePointerId = event.getPointerId(newPointerIndex);
}
break;
}
}
return true;
}
private class ScaleGestureListener
extends ScaleGestureDetector.SimpleOnScaleGestureListener {
private float mPivotX;
private float mPivotY;
private Vector2D mPrevSpanVector = new Vector2D();
@Override
public boolean onScaleBegin(View view, ScaleGestureDetector detector) {
mPivotX = detector.getFocusX();
mPivotY = detector.getFocusY();
mPrevSpanVector.set(detector.getCurrentSpanVector());
return true;
}
@Override
public boolean onScale(View view, ScaleGestureDetector detector) {
TransformInfo info = new TransformInfo();
info.deltaScale = isScaleEnabled ? detector.getScaleFactor() : 1.0f;
info.deltaAngle = isRotateEnabled ?
Vector2D.getAngle(mPrevSpanVector, detector.getCurrentSpanVector()) : 0.0f;
info.deltaX = isTranslateEnabled ? detector.getFocusX() - mPivotX : 0.0f;
info.deltaY = isTranslateEnabled ? detector.getFocusY() - mPivotY : 0.0f;
info.pivotX = mPivotX;
info.pivotY = mPivotY;
info.minimumScale = minimumScale;
info.maximumScale = maximumScale;
move(view, info);
return false;
}
}
private class TransformInfo {
public float deltaX;
public float deltaY;
public float deltaScale;
public float deltaAngle;
public float pivotX;
public float pivotY;
public float minimumScale;
public float maximumScale;
@Override public String toString() {
return "TransformInfo{" +
"deltaX=" + deltaX +
", deltaY=" + deltaY +
", deltaScale=" + deltaScale +
", deltaAngle=" + deltaAngle +
", pivotX=" + pivotX +
", pivotY=" + pivotY +
", minimumScale=" + minimumScale +
", maximumScale=" + maximumScale +
'}';
}
}
}