Intereting Posts
Добавить программный продукт для recyclerview? Представление списка задает настраиваемый селектор пульсаций Получите предпочтительную строку формата даты системы Android R.java исчезает после очистки проекта HonyComb и DefaultHttpClient Android, как я могу получить список всех файлов в папке? Android: проверьте, разрешены ли службы определения местоположения с помощью поставщика плавного доступа Как отключить или включить прокрутку viewpager в android Тестирование Android-модуля с помощью дооснащения и моккита Невозможно установить флаг отладки в AndroidManifest.xml Показать миллисекунды с помощью Android Chronometer Десятичный разделитель запятой (',') с номеромDecimal inputType в EditText Почему Android Studio не позволяет мне создавать классы Java? Android FacebookSDK с помощью встроенного приложения Facebook запрашивает разрешения даже после того, как пользователь уже дал им Как импортировать класс android.support.v7.app.NotificationCompat.Builder в Android Studio

Внедрение масштабирования и перетаскивания с использованием сборки 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); 

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