Intereting Posts
Доступ к Google плюс клиенту из нескольких действий Остановить CollapsingToolbar от сбрасывания после того, как NestedScrollView закончил контент для прокрутки «Не удалось получить системную библиотеку для проекта» после обновления до Android SDK 2.3 и ADT 8.0 Как поддерживать MOV (быстрое время) в Android? Андроидный эмулятор не запускается на ubuntu 12.04 после запуска из ssh Не удалось найти метод onClick (View) в активности Получать обновленный счет строк из SQLite в Android с использованием необработанного запроса? Настройка Eclipse для использования подписанного хранилища ключей Что такое класс адаптера? NavUtils.navigateUpTo () не запускает никаких действий Android Toast эквивалент в iOS Как я могу сделать свой Android SwipeableCardView больше похожим на почтовое приложение IOS 7 (проведите по экрану, чтобы показать кнопки) Как построить i686-linux-android-gfortran для android-ndk8b (x86 arch Android)? Включить библиотеку Boost C ++ в android ImageButton в Android с прозрачным фоном

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

Поэтому я расширяю пользовательский 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); Затем вычисляет физический размер экрана в пикселях, преобразует его в метры и, наконец, применяет масштабный коэффициент, поэтому все нарисованные объекты смещаются правильно.

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