Durchführen von Prise Zoom und Ziehen mit Android's Build in Gesten Zuhörer und Skala Zuhörer

Ich versuche, Pinch-Zoom zu implementieren und mit Android-Gesten-Listener und Skala-Hörer zu ziehen. Das Problem ist, dass, wenn ich Pinch Zoom, das Bild (die ich versuche zu zoomen) springt auf einen bestimmten Ort. Auch die Zoomposition ist nicht zentriert. Der folgende Code zeigt, was ich zu erreichen versuche. Jede Idee, warum das Bild springt (und wie man es korrigiert)?

public class CustomView extends View { Bitmap image; int screenHeight; int screenWidth; Paint paint; GestureDetector gestures; ScaleGestureDetector scaleGesture; float scale = 1.0f; float horizontalOffset, verticalOffset; int NORMAL = 0; int ZOOM = 1; int DRAG = 2; boolean isScaling = false; float touchX, touchY; int mode = NORMAL; public CustomView(Context context) { super(context); //initializing variables image = BitmapFactory.decodeResource(getResources(), R.drawable.image_name); //This is a full screen view screenWidth = getResources().getDisplayMetrics().widthPixels; screenHeight = getResources().getDisplayMetrics().heightPixels; paint = new Paint(); paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); paint.setColor(Color.WHITE); scaleGesture = new ScaleGestureDetector(getContext(), new ScaleListener()); gestures = new GestureDetector(getContext(), new GestureListener()); mode = NORMAL; initialize(); } //Best fit image display on canvas private void initialize() { float imgPartRatio = image.getWidth() / (float) image.getHeight(); float screenRatio = (float) screenWidth / (float) screenHeight; if (screenRatio > imgPartRatio) { scale = ((float) screenHeight) / (float) (image.getHeight()); // fit height horizontalOffset = ((float) screenWidth - scale * (float) (image.getWidth())) / 2.0f; verticalOffset = 0; } else { scale = ((float) screenWidth) / (float) (image.getWidth()); // fit width horizontalOffset = 0; verticalOffset = ((float) screenHeight - scale * (float) (image.getHeight())) / 2.0f; } invalidate(); } @Override protected void onDraw(Canvas canvas) { canvas.save(); canvas.drawColor(0, Mode.CLEAR); canvas.drawColor(Color.WHITE); if(mode == DRAG || mode == NORMAL) { //This works perfectly as expected canvas.translate(horizontalOffset, verticalOffset); canvas.scale(scale, scale); canvas.drawBitmap(image, getMatrix(), paint); } else if (mode == ZOOM) { //PROBLEM AREA - when applying pinch zoom, //the image jumps to a position abruptly canvas.scale(scale, scale, touchX, touchY); canvas.drawBitmap(image, getMatrix(), paint); } canvas.restore(); } public class ScaleListener implements OnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { float scaleFactorNew = detector.getScaleFactor(); if (detector.isInProgress()) { touchX = detector.getFocusX(); touchY = detector.getFocusY(); scale *= scaleFactorNew; invalidate(0, 0, screenWidth, screenHeight); } return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { isScaling = true; mode=ZOOM; return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { mode = NORMAL; isScaling = false; } } public class GestureListener implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener { @Override public boolean onDown(MotionEvent e) { isScaling = false; return true; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (!isScaling) { mode = DRAG; isScaling = false; horizontalOffset -= distanceX; verticalOffset -= distanceY; invalidate(0, 0, screenWidth, screenHeight); } else { mode = ZOOM; isScaling = true; } return true; } } @Override public boolean onTouchEvent(MotionEvent event) { scaleGesture.onTouchEvent(event); gestures.onTouchEvent(event); return true; } } 

Danke im Voraus.

  • Unterschied zwischen <include> und <ViewStub> in android
  • Wie kann man ganze Werte (ganze Zahlen) nur in Ratingbars zulassen?
  • Gradle Error: Execution fehlgeschlagen für Task ': app: processDebugGoogleServices'
  • HonyComb und DefaultHttpClient
  • Build Unsigned APK mit Gradle
  • Java.lang.IllegalArgumentException: Unzulässiges Zeichen im Schema bei Index 0:
  • Ist eine "Globals" -Klasse mit statischen Variablen in Android sicher?
  • Überprüfen Sie, ob der Dienst auf Android läuft?
  • Android SIP API: Shows unterstützt, aber Fehler 'nicht unterstützt'
  • Wie man eine benutzerdefinierte Schriftart im ActionBar-Titel festlegt?
  • Android bekommt Bildpfad von zeichen als String
  • Android: View.getTag / setTag und IllegalArgumentException
  • One Solution collect form web for “Durchführen von Prise Zoom und Ziehen mit Android's Build in Gesten Zuhörer und Skala Zuhörer”

    Ich habe dieses Verhalten implementiert, und ich habe eine Matrix verwendet, um alle Zooming und Scrollen (und Rotation, in meinem Fall) zu behandeln. Es macht für ordentlichen Code und funktioniert wie Uhrwerk.

    Eine Matrix als Klassenmitglied speichern:

     Matrix drawMatrix; 

    Bearbeiten: Speichern Sie den alten Fokuspunkt, um die Fokusverschiebung während der Skalierung zu erhalten.

     float lastFocusX; float lastFocusY; 

    Bearbeiten : Legen Sie lastFocus-Variablen in onScaleBegin fest

     @Override public boolean onScaleBegin(ScaleGestureDetector detector) { lastFocusX = detector.getFocusX(); lastFocusY = detector.getFocusY(); return true; } 

    Ersetzen Sie Ihre onScale:

     @Override public boolean onScale(ScaleGestureDetector detector) { Matrix transformationMatrix = new Matrix(); float focusX = detector.getFocusX(); float focusY = detector.getFocusY(); //Zoom focus is where the fingers are centered, transformationMatrix.postTranslate(-focusX, -focusY); transformationMatrix.postScale(detector.getScaleFactor(), detector.getScaleFactor()); /* Adding focus shift to allow for scrolling with two pointers down. Remove it to skip this functionality. This could be done in fewer lines, but for clarity I do it this way here */ //Edited after comment by chochim float focusShiftX = focusX - lastFocusX; float focusShiftY = focusY - lastFocusY; transformationMatrix.postTranslate(focusX + focusShiftX, focusY + focusShiftY); drawMatrix.postConcat(transformationMatrix); lastFocusX = focusX; lastFocusY = focusY; invalidate(); return true; } 

    Ähnlich in onScroll:

     @Override public boolean onScroll(MotionEvent downEvent, MotionEvent currentEvent, float distanceX, float distanceY) { drawMatrix.postTranslate(-distanceX, -distanceY); invalidate(); return true; } 

    In onDraw; Zeichne mit deinem DrawMatrix:

     canvas.drawBitmap(image, drawMatrix, paint); 

    Glückliche Kodierung!

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.