Intereting Posts
Как настроить Proguard с помощью Gradle? GCM Key для приложений браузера (со ссылками) неактивен Библиотека поддержки Android 23.4.0: android.support.v7.widget.TintContextWrapper не может быть перенесена в Activity Как стиль цвета курсора SearchView в AppCompat SetRetainInstance (true) + setCustomAnimations (…) = анимация для каждого изменения ориентации? Удаление плагинов cordova из проекта Как я могу использовать Android KeyStore для безопасного хранения произвольных строк? Моши против Гссона в андроиде Android TextView Обоснование текста Как добавить программный оттенок Ошибка после добавления зависимостей к Action Bar Sherlock в Android Studio 0.5.8 Как переопределить стили библиотеки, которая имеет свою собственную активность Фрагментные транзакции с переходом – Требуются уникальные имена перехода ViewPager + FragmentPagerAdapter внутри DialogFragment получает «IllegalArgumentException: просмотр не найден …» В Android Webview я могу изменить DOM веб-страницы?

Как я могу разместить ограничения на матрицу перевода холста?

Поэтому я расширяю пользовательский SurfaceView и SurfaceView сделать его SurfaceView для масштабирования и прокрутки.

Как я прокручиваю:

  @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // subtract scrolled amount matrix.postTranslate(-distanceX, -distanceY); rebound(); invalidate(); // handled return true; } 

Как увеличить масштаб:

  @Override public boolean onScale(ScaleGestureDetector detector) { if (detector.isInProgress()) { // get scale float factor = detector.getScaleFactor(); // Don't let the object get too small or too large. if (factor * scale > 1f) { factor = 1f / scale; } else if (factor * scale < minScale) { factor = minScale / scale; } // store local scale scale *= factor; // do the scale matrix.preScale(factor, factor, detector.getFocusX(), detector.getFocusY()); rebound(); invalidate(); } return true; } 

(Для справки я использую этот код для onDraw 🙂

 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.setMatrix(matrix); // [...] stuff drawn with matrix settings canvas.restore(); // [...] stuff drawn without matrix settings, as an overlay } 

В настоящее время оба этих метода функционируют хорошо. Масштабирование останавливается с минимальным (между 0f и 1f) и максимальным (в настоящее время всегда 1f) значением шкалы правильно.

Используемые глобальные поля:

  • drawW , drawH = float , размер в пикселях данных холста в масштабе = 1.
  • parentW , parentH = float , размер в пикселях видимого вида.
  • matrix = android.graphics.Matrix .

Проблема в том, что метод « rebound() » (возможно, нуждается в более лучшем имени, хех), который я пытаюсь реализовать, что автоматически заставит содержимое оставаться в поле зрения.

Я пробовал различные методы, чтобы попытаться вычислить, где должны быть границы (в пределах прямоугольника (0, 0, parentW, parentH)) и перевести матрицу «назад», когда она заходит слишком далеко.

Вот то, что у меня есть сейчас, что определенно не работает, вместо этого вдавливая его дальше вправо. Я чувствую, что проблема – это моя математика, а не моя идея. Может кто-нибудь, пожалуйста, придумать более простой или более чистый код, который переводит матрицу на край, если ее слишком далеко и / или устранить проблемы с моей попыткой этой реализации? Проверки, используемые для его отображения в левом верхнем углу

 public void rebound() { // bounds RectF currentBounds = new RectF(0, 0, drawW, drawH); matrix.mapRect(currentBounds); RectF parentBounds = new RectF(0, 0, parentW, parentH/2); PointF diff = new PointF(0, 0); if (currentBounds.left > parentBounds.left) { diff.x += (parentBounds.left - currentBounds.left); } if (currentBounds.top > parentBounds.top) { diff.y += (parentBounds.top - currentBounds.top); } if (currentBounds.width() > parentBounds.width()) { if (currentBounds.right < parentBounds.right) { diff.x += (parentBounds.right - currentBounds.right); } if (currentBounds.bottom < parentBounds.bottom) { diff.y += (parentBounds.bottom - currentBounds.bottom); } } matrix.postTranslate(diff.x, diff.y); } 

Предыдущая версия, которую я написал перед матрицей, была полем (я просто использовал canvas.scale() затем canvas.translate() в onDraw ), который работал:

 public void rebound() { // bounds int boundTop = 0; int boundLeft = 0; int boundRight = (int)(-scale * drawW + parentW); int boundBottom = (int)(-scale * drawH + parentH); if (boundLeft >= boundRight) { mScrollX = Math.min(boundLeft, Math.max(boundRight, mScrollX)); } else { mScrollX = 0; } if (boundTop >= boundBottom) { mScrollY = Math.min(boundTop, Math.max(boundBottom, mScrollY)); } else { mScrollY = 0; } } 

Я использую новый способ, чтобы я мог правильно масштабировать по центру detector.getFocusX() , detector.getFocusY() .

UPDATE : я изменил метод на то, что он сейчас. Он работает только несколько, все еще ограничивая направление направления y вне центра и не работает после изменения уровней масштабирования. Я также сделал это «preScale» и «postTranslate», чтобы (как я понимаю) он всегда должен применять масштаб, а затем переводить, а не смешивать их.

ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ : Он работает сейчас. Вот рабочий метод rebound с комментариями:

 public void rebound() { // make a rectangle representing what our current canvas looks like RectF currentBounds = new RectF(0, 0, drawW, drawH); matrix.mapRect(currentBounds); // make a rectangle representing the scroll bounds RectF areaBounds = new RectF((float) getLeft(), (float) getTop(), (float) parentW + (float) getLeft(), (float) parentH + (float) getTop()); // the difference between the current rectangle and the rectangle we want PointF diff = new PointF(0f, 0f); // x-direction if (currentBounds.width() > areaBounds.width()) { // allow scrolling only if the amount of content is too wide at this scale if (currentBounds.left > areaBounds.left) { // stop from scrolling too far left diff.x = (areaBounds.left - currentBounds.left); } if (currentBounds.right < areaBounds.right) { // stop from scrolling too far right diff.x = (areaBounds.right - currentBounds.right); } } else { // negate any scrolling diff.x = (areaBounds.left - currentBounds.left); } // y-direction if (currentBounds.height() > areaBounds.height()) { // allow scrolling only if the amount of content is too tall at this scale if (currentBounds.top > areaBounds.top) { // stop from scrolling too far above diff.y = (areaBounds.top - currentBounds.top); } if (currentBounds.bottom < areaBounds.bottom) { // stop from scrolling too far below diff.y = (areaBounds.bottom - currentBounds.bottom); } } else { // negate any scrolling diff.y = (areaBounds.top - currentBounds.top); } // translate matrix.postTranslate(diff.x, diff.y); } 

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

Solutions Collecting From Web of "Как я могу разместить ограничения на матрицу перевода холста?"

Я реализовал что-то в этом роде, чтобы перевернуть мой собственный пинч для увеличения. Я подозреваю, что проблема с вашей осью y, находящейся вне центра, может быть ниже представления, не являющегося полноэкранным размером, или вы не можете изменять координаты для соответствия шкале.

Моя реализация вычисляет масштабный коэффициент, применяет его с помощью: canvas.scale (pinchZoomScale, pinchZoomScale); Затем вычисляет физический размер экрана в пикселях, преобразует его в метры и, наконец, применяет масштабный коэффициент, поэтому все нарисованные объекты смещаются правильно.

Эта реализация основана на том, чтобы всегда знать, что должно быть в центре экрана и запираться на нем, независимо от уровня масштабирования.