English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Обзор: С помощью пользовательского компонента ImageView, вызываемого в xml-разметке, можно масштабировать изображения.
/** * Управление ImageView на основе пользовательских функций, поддерживающее многоточечное масштабирование и перетаскивание изображений * * @author qiuwanyong */ public class MyImageView extends ImageView { /** * Константа состояния инициализации */ public static final int STATUS_INIT = 1; /** * Константа состояния увеличения изображения */ public static final int STATUS_ZOOM_OUT = 2; /** * Константа состояния уменьшения изображения */ public static final int STATUS_ZOOM_IN = 3; /** * Константа состояния перетаскивания изображения */ public static final int STATUS_MOVE = 4; /** * Мatrix для перемещения и масштабирования изображения */ private Matrix matrix = new Matrix(); /** * Bitmap объект для отображения */ private Bitmap sourceBitmap; /** * Запись текущего состояния операции, возможные значения: STATUS_INIT, STATUS_ZOOM_OUT, STATUS_ZOOM_IN и STATUS_MOVE */ private int currentStatus; /** * Ширина контроллера ZoomImageView */ private int width; /** * Высота контроллера ZoomImageView */ private int height; /** * Запись координаты X центральной точки при одновременном放置 двух пальцев на экране */ private float centerPointX; /** * Запись координаты Y центральной точки при одновременном放置 двух пальцев на экране */ private float centerPointY; /** * Запись текущей ширины изображения, при масштабировании изображения этот параметр изменяется */ private float currentBitmapWidth; /** * Запись текущей высоты изображения, при масштабировании изображения этот параметр изменяется */ private float currentBitmapHeight; /** * Запись координаты X последнего перемещения пальца */ private float lastXMove = -1; /** * Запись координаты Y последнего перемещения пальца */ private float lastYMove = -1; /** * Запись расстояния перемещения пальца по горизонтали */ private float movedDistanceX; /** * Запись расстояния перемещения пальца по вертикальной координате */ private float movedDistanceY; /** * Записывает горизонтальное смещение изображения в матрице */ private float totalTranslateX; /** * Записывает вертикальное смещение изображения в матрице */ private float totalTranslateY; /** * Записывает общее масштабирование изображения в матрице */ private float totalRatio; /** * Записывает масштаб, вызванный перемещением пальцев */ private float scaledRatio; /** * Записывает масштаб изображения при его инициализации */ private float initRatio; /** * Записывает上次 расстояние между двумя пальцами */ private double lastFingerDis; /** * Конструктор ZoomImageView, устанавливает текущий статус на STATUS_INIT. * * @param context * @param attrs */ public MyImageView(Context context, AttributeSet attrs) { super(context, attrs); currentStatus = STATUS_INIT; } /** * Установите изображение для отображения. * * @param bitmap * Bitmap объект для отображения */ public void setImageBitmap(Bitmap bitmap) { sourceBitmap = bitmap; invalidate(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (changed) { // Отдельно получаем ширину и высоту ZoomImageView width = getWidth(); height = getHeight(); } } @SuppressLint("NewApi") @Override public boolean onTouchEvent(MotionEvent event) { if (initRatio == totalRatio) { getParent().requestDisallowInterceptTouchEvent(false); } else { getParent().requestDisallowInterceptTouchEvent(true); } switch (event.getActionMasked()) { case MotionEvent.ACTION_POINTER_DOWN: if (event.getPointerCount() == 2) { // При нажатии двух пальцев на экран, вычисляется расстояние между пальцами lastFingerDis = distanceBetweenFingers(event); } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_MOVE: if (event.getPointerCount() == 1) { // Только при движении одного пальца по экрану, это состояние перетаскивания float xMove = event.getX(); float yMove = event.getY(); if (lastXMove == -1 && lastYMove == -1) { lastXMove = xMove; lastYMove = yMove; } currentStatus = STATUS_MOVE; movedDistanceX = xMove - lastXMove; movedDistanceY = yMove - lastYMove; // Выполнение проверки границ, не разрешается вывести изображение за пределы границ if (totalTranslateX + movedDistanceX > 0) { movedDistanceX = 0; } else if (width - (totalTranslateX + movedDistanceX) > currentBitmapWidth) { movedDistanceX = 0; } if (totalTranslateY + movedDistanceY > 0) { movedDistanceY = 0; } else if (height - (totalTranslateY + movedDistanceY) > currentBitmapHeight) { movedDistanceY = 0; } // Вызов метода onDraw() для рисования изображения invalidate(); lastXMove = xMove; lastYMove = yMove; } else if (event.getPointerCount() == 2) { // У двух пальцев нажимается на экран и перемещается, это состояние масштабирования centerPointBetweenFingers(event); if (fingerDis > lastFingerDis) { currentStatus = STATUS_ZOOM_OUT; currentStatus = STATUS_ZOOM_IN; } else { // Проверка коэффициента масштабирования, максимальное увеличение изображения до 4 раз, минимальное уменьшение до начального коэффициента } if ((currentStatus == STATUS_ZOOM_OUT && totalRatio < 4 * initRatio) || (currentStatus == STATUS_ZOOM_IN && totalRatio > initRatio)) { scaledRatio = (float) (fingerDis / lastFingerDis); totalRatio = totalRatio * scaledRatio; if (totalRatio > 4 * initRatio) { totalRatio = 4 * initRatio; else if (totalRatio < initRatio) { } totalRatio = initRatio; } // Вызов метода onDraw() для рисования изображения invalidate(); lastFingerDis = fingerDis; } } break; case MotionEvent.ACTION_POINTER_UP: if (event.getPointerCount() == 2) { // Возвращение временных значений к начальным при выходе пальца за пределы экрана lastXMove = -1; lastYMove = -1; } break; case MotionEvent.ACTION_UP: // Возвращение временных значений к начальным при выходе пальца за пределы экрана lastXMove = -1; lastYMove = -1; break; default: break; } return true; } /** * В зависимости от значения currentStatus выполняется определенная операция рисования изображения. */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); switch (currentStatus) { case STATUS_ZOOM_OUT: case STATUS_ZOOM_IN: zoom(canvas); break; case STATUS_MOVE: move(canvas); break; case STATUS_INIT: initBitmap(canvas); default: if (sourceBitmap != null) { canvas.drawBitmap(sourceBitmap, matrix, null); } break; } } /** * Обработать изображение масштабирования. * * @param canvas */ private void zoom(Canvas canvas) { matrix.reset(); // Масштабировать изображение по общей масштабирующей пропорции matrix.postScale(totalRatio, totalRatio); float scaledWidth = sourceBitmap.getWidth() * totalRatio; float scaledHeight = sourceBitmap.getHeight() * totalRatio; float translateX = 0f; float translateY = 0f; // Если текущая ширина изображения меньше ширины экрана, то масштабировать изображение по горизонтали по координате центра экрана. В противном случае, по координате центра两点. if (currentBitmapWidth < width) { translateX = (width - scaledWidth) / 2f; } else { translateX = totalTranslateX * scaledRatio + centerPointX * (1 - scaledRatio); // Выполнить проверку границ, чтобы после масштабирования изображения оно не сместилось за экран в горизонтальном направлении if (translateX > 0) { translateX = 0; } else if (width - translateX > scaledWidth) { translateX = width - scaledWidth; } } // Если текущая высота изображения меньше высоты экрана, то масштабировать изображение по вертикали по координате центра экрана. В противном случае, по координате центра两点. if (currentBitmapHeight < height) { translateY = (height - scaledHeight) / 2f; } else { translateY = totalTranslateY * scaledRatio + centerPointY * (1 - scaledRatio); // Выполнить проверку границ, чтобы после масштабирования изображения оно не сместилось за экран в вертикальном направлении if (translateY > 0) { translateY = 0; else if (height - translateY > scaledHeight) { translateY = height - scaledHeight; } } // После масштабирования изображение смещается, чтобы сохранить центральное положение matrix.postTranslate(translateX, translateY); totalTranslateX = translateX; totalTranslateY = translateY; currentBitmapWidth = scaledWidth; currentBitmapHeight = scaledHeight; canvas.drawBitmap(sourceBitmap, matrix, null); } /** * Выполняет трансляцию изображения * * @param canvas */ private void move(Canvas canvas) { matrix.reset(); // Вычисляется общее смещение в зависимости от расстояния перемещения пальца float translateX = totalTranslateX + movedDistanceX; float translateY = totalTranslateY + movedDistanceY; // Сначала изображение масштабируется по уже существующему коэффициенту масштабирования matrix.postScale(totalRatio, totalRatio); // Затем выполняется смещение в зависимости от расстояния перемещения matrix.postTranslate(translateX, translateY); totalTranslateX = translateX; totalTranslateY = translateY; canvas.drawBitmap(sourceBitmap, matrix, null); } /** * Включает инициализацию изображения, включая выравнивание изображения по центру и его уменьшение пропорционально, если оно больше экрана * * @param canvas */ private void initBitmap(Canvas canvas) { if (sourceBitmap != null) { matrix.reset(); int bitmapWidth = sourceBitmap.getWidth(); int bitmapHeight = sourceBitmap.getHeight(); if (bitmapWidth > width || bitmapHeight > height) { if (bitmapWidth - width > bitmapHeight - height) { // Если ширина изображения больше ширины экрана, то изображение уменьшается пропорционально, чтобы его можно было полностью показать float ratio = width / (bitmapWidth * 1.0f); matrix.postScale(ratio, ratio); float translateY = (height - (bitmapHeight * ratio)) / 2f; // В направлении координаты Y выполняется смещение, чтобы обеспечить выравнивание изображения по центру matrix.postTranslate(0, translateY); totalTranslateY = translateY; totalRatio = initRatio = ratio; } else { // Если высота изображения больше высоты экрана, то изображение уменьшается пропорционально, чтобы его можно было полностью показать float ratio = height / (bitmapHeight * 1.0f); matrix.postScale(ratio, ratio); float translateX = (width - (bitmapWidth * ratio)) / 2f; // Проводится смещение по горизонтали, чтобы изображение выровнялось по центру matrix.postTranslate(translateX, 0); totalTranslateX = translateX; totalRatio = initRatio = ratio; } currentBitmapWidth = bitmapWidth * initRatio; currentBitmapHeight = bitmapHeight * initRatio; } else { // Когда ширина и высота изображения меньше ширины и высоты экрана, изображение выравнивается по центру float translateX = (width - sourceBitmap.getWidth()) / 2f; float translateY = (height - sourceBitmap.getHeight()) / 2f; matrix.postTranslate(translateX, translateY); totalTranslateX = translateX; totalTranslateY = translateY; totalRatio = initRatio = 1f; currentBitmapWidth = bitmapWidth; currentBitmapHeight = bitmapHeight; } canvas.drawBitmap(sourceBitmap, matrix, null); } } /** * Рассчитывает расстояние между двумя пальцами. * * @param event * @return Расстояние между двумя пальцами */ @SuppressLint("NewApi") private double distanceBetweenFingers(MotionEvent event) { float disX = Math.abs(event.getX(0) - event.getX(1)); float disY = Math.abs(event.getY(0) - event.getY(1)); return Math.sqrt(disX * disX + disY * disY); } /** * Вычислить координаты центра между двумя пальцами. * * @param event */ @SuppressLint("NewApi") private void centerPointBetweenFingers(MotionEvent event) { float xPoint0 = event.getX(0); float yPoint0 = event.getY(0); float xPoint1 = event.getX(1); float yPoint1 = event.getY(1); centerPointX = (xPoint0 + xPoint1) / 2; centerPointY = (yPoint0 + yPoint1) / 2; } }
Вызов в макете
Приведенный выше код для реализации масштабирования и拖ания изображения через пользовательский控件 ImageView для Android, представлен редактором. Надеюсь, это поможет вам. Если у вас есть какие-либо вопросы, пожалуйста, оставьте комментарий, редактор ответит вам своевременно. В этом regard, мы также очень благодарны всем за поддержку сайта呐喊 учебник!
Декларация: содержимое этой статьи взято из Интернета, авторские права принадлежат соответствующему автору. Контент был предоставлен пользователями Интернета, веб-сайт не имеет права собственности на него, не был отредактирован вручную и не несет ответственности за него. Если вы обнаружите материалы,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (во время отправки письма замените # на @),并提供相关证据. Если подтвердится, что материалы являются нарушающими авторские права, сайт немедленно удалят.