Intereting Posts
Как использовать AutoScrollHelper Отношения между dip, px и dpi Лучшие варианты, чем backporting ICS HttpResponseCache Английский код языка США изменился? Google Speech Api v2 не возвращает правильный результат Android AudioRecord заставляет другой поток использовать источник аудиосигнала MIC Как нарисовать дугу между двумя точками на холсте? LG L90 не устанавливает драйверы debug usb Установка уровня альфа на вид не работает Как проверить размер зависимостей в приложении Android? Как начать другое действие с некоторой задержкой после нажатия кнопки в android? Как обрабатывать сообщения обработчика, когда действие / фрагмент приостановлено Как вы читаете уникальный идентификатор тега NFC на Android? Пока не удалось достичь Gapless аудио-цикла на Android Как я могу масштабировать текстовые изображения, используя общие переходы элементов? Как совместно использовать изображение + текст, используя ACTION_SEND в android?

Внедрение масштабирования и перетаскивания с использованием сборки Android в прослушивании жестов и прослушивании шкалы

Я пытаюсь реализовать масштабирование и перетаскивание с помощью прослушивателя жестов Android и прослушивателя шкалы. Проблема в том, что когда я выполняю масштабирование, изображение (которое я пытаюсь увеличить) отскакивает в определенное место. Также положение масштабирования не центрировано. Следующий код демонстрирует, чего я пытаюсь достичь. Любая идея, почему изображение прыгает (и как его исправить)?

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

Заранее спасибо.

Solutions Collecting From Web of "Внедрение масштабирования и перетаскивания с использованием сборки Android в прослушивании жестов и прослушивании шкалы"

Я реализовал это поведение, и я использовал матрицу для обработки всех масштабирования и прокрутки (и вращения в моем случае). Он обеспечивает аккуратный код и работает как часы.

Храните матрицу в качестве члена класса:

 Matrix drawMatrix; 

Изменить: сохранить старую точку фокусировки, используемую для сдвига фокуса при масштабировании.

 float lastFocusX; float lastFocusY; 

Изменить : установить переменные lastFocus в onScaleBegin

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

Замените 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; } 

Аналогично в onScroll:

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

В onDraw; Нарисуйте с помощью drawMatrix:

 canvas.drawBitmap(image, drawMatrix, paint); 

Счастливое кодирование!