English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Resumen: a través de la personalización del controlador ImageView, se puede llamar al componente personalizado en el layout xml para realizar el escalado de imágenes.
/** * controlador de ImageView personalizado, que permite realizar escalado y arrastre multi-punto de imágenes * * @author qiuwanyong */ public class MyImageView extends ImageView { /** * constante de estado de inicialización */ public static final int STATUS_INIT = 1; /** * constante de estado de ampliación de imagen */ public static final int STATUS_ZOOM_OUT = 2; /** * constante de estado de reducción de imagen */ public static final int STATUS_ZOOM_IN = 3; /** * constante de estado de arrastre de imagen */ public static final int STATUS_MOVE = 4; /** * matriz utilizada para realizar transformaciones de desplazamiento y escalado de imágenes */ private Matrix matrix = new Matrix(); /** * el objeto Bitmap que se mostrará */ private Bitmap sourceBitmap; /** * registra el estado de la operación actual, los valores opcionales son STATUS_INIT, STATUS_ZOOM_OUT, STATUS_ZOOM_IN y STATUS_MOVE */ private int currentStatus; /** * El ancho del control de ZoomImageView. */ private int width; /** * La altura del control de ZoomImageView. */ private int height; /** * Registrar el valor de la coordenada x del punto central cuando los dos dedos están en la pantalla. */ private float centerPointX; /** * Registrar el valor de la coordenada y del punto central cuando los dos dedos están en la pantalla. */ private float centerPointY; /** * Registrar el ancho actual de la imagen, este valor cambiará cuando la imagen se escalde. */ private float currentBitmapWidth; /** * Registrar la altura actual de la imagen, este valor cambiará cuando la imagen se escalde. */ private float currentBitmapHeight; /** * Registrar la coordenada x del movimiento del dedo la última vez. */ private float lastXMove = -1; /** * Registrar la coordenada y del movimiento del dedo la última vez. */ private float lastYMove = -1; /** * Registrar la distancia de movimiento del dedo en el eje horizontal. */ private float movedDistanceX; /** * Registrar la distancia de movimiento del dedo en el eje vertical. */ private float movedDistanceY; /** * Registrar el valor de desplazamiento horizontal de la imagen en la matriz. */ private float totalTranslateX; /** * Registrar el valor de desplazamiento vertical de la imagen en la matriz. */ private float totalTranslateY; /** * Registrar la proporción total de escalado de la imagen en la matriz. */ private float totalRatio; /** * Registrar la proporción de escalado causada por el movimiento de los dedos. */ private float scaledRatio; /** * Registrar la proporción de escalado de la imagen al inicializar. */ private float initRatio; /** * Registrar la distancia entre los dos dedos la última vez. */ private double lastFingerDis; /** * El constructor de ZoomImageView, establece el estado de operación actual en STATUS_INIT. * * @param context * @param attrs */ public MyImageView(Context context, AttributeSet attrs) { super(context, attrs); currentStatus = STATUS_INIT; } /** * Establezca la imagen que se mostrará. * * @param bitmap * el objeto Bitmap que se mostrará */ 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) { // obtener respectivamente el ancho y la altura de 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) { // cuando hay dos dedos presionados en la pantalla, calcular la distancia entre los dedos lastFingerDis = distanceBetweenFingers(event); } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_MOVE: if (event.getPointerCount() == 1) { // sólo cuando un dedo está presionado y se mueve en la pantalla, el estado es de arrastrar 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; // realizar una verificación de límites, no se permite que la imagen se arrastre más allá de los límites if (totalTranslateX + movedDistanceX > 0) {}} movedDistanceX = 0; } else if (width - (totalTranslateX + movedDistanceX) > currentBitmapWidth) { movedDistanceX = 0; } if (totalTranslateY + movedDistanceY > 0) { movedDistanceY = 0; } else if (height - (totalTranslateY + if (movedDistanceY) > currentBitmapHeight) { movedDistanceY = 0; } // Llamar al método onDraw() para dibujar la imagen invalidate(); lastXMove = xMove; lastYMove = yMove; } else if (event.getPointerCount() == 2) { // Cuando hay dos dedos presionando y moviéndose en la pantalla, se está en estado de escala centerPointBetweenFingers(event); double fingerDis = distanceBetweenFingers(event); if (fingerDis > lastFingerDis) { currentStatus = STATUS_ZOOM_OUT; } else { currentStatus = STATUS_ZOOM_IN; } // realizar una verificación de la multiplicidad de escala, solo se permite ampliar la imagen4veces, puede reducirse al tamaño inicial 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; } // Llamar al método onDraw() para dibujar la imagen invalidate(); lastFingerDis = fingerDis; } } break; case MotionEvent.ACTION_POINTER_UP: if (event.getPointerCount() == 2) { // Restaurar los valores temporales cuando el dedo se separa de la pantalla lastXMove = -1; lastYMove = -1; } break; case MotionEvent.ACTION_UP: // Restaurar los valores temporales cuando el dedo se separa de la pantalla lastXMove = -1; lastYMove = -1; break; default: break; } return true; } /** * Determine qué tipo de operación de dibujo se realiza en la imagen según el valor de 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; } } /** * Realizar el procesamiento de escalada de la imagen. * * @param canvas */ private void zoom(Canvas canvas) { matrix.reset(); // Escalar la imagen según la proporción total de escalada matrix.postScale(totalRatio, totalRatio); float scaledWidth = sourceBitmap.getWidth() * totalRatio; float scaledHeight = sourceBitmap.getHeight() * totalRatio; float translateX = 0f; float translateY = 0f; // Si la anchura de la imagen actual es menor que la anchura de la pantalla, se realiza una escalada horizontal en el eje horizontal del centro de la pantalla. De lo contrario, se realiza una escalada horizontal en el eje horizontal del centro de los dos dedos. if (currentBitmapWidth < width) { translateX = (width - scaledWidth) / 2f; } else { translateX = totalTranslateX * scaledRatio + centerPointX * (1 - scaledRatio); // Realizar comprobación de límites para asegurar que la imagen, después de la escalada, no se desplace hacia afuera de la pantalla en la dirección horizontal if (translateX > 0) { translateX = 0; } else if (width - translateX > scaledWidth) { translateX = width - scaledWidth; } } // Si la altura de la imagen actual es menor que la altura de la pantalla, se realiza una escalada vertical en el eje vertical del centro de la pantalla. De lo contrario, se realiza una escalada vertical en el eje vertical del centro de los dos dedos. if (currentBitmapHeight < height) { translateY = (height - scaledHeight) / 2f; } else { translateY = totalTranslateY * scaledRatio + centerPointY * (1 - scaledRatio); // Se realiza la verificación de límites para garantizar que la imagen no se desplace hacia afuera de la pantalla en la dirección vertical después de la escalada if (translateY > 0) { translateY = 0; } else if (height - translateY > scaledHeight) { translateY = height - scaledHeight; } } // Se realiza el desplazamiento de la imagen después de la escalada para garantizar que el punto central no cambie después de la escalada matrix.postTranslate(translateX, translateY); totalTranslateX = translateX; totalTranslateY = translateY; currentBitmapWidth = scaledWidth; currentBitmapHeight = scaledHeight; canvas.drawBitmap(sourceBitmap, matrix, null); } /** * Se realiza el tratamiento de desplazamiento de la imagen * * @param canvas */ private void move(Canvas canvas) { matrix.reset(); // Se calcula el valor de desplazamiento total según la distancia de desplazamiento del dedo float translateX = totalTranslateX + movedDistanceX; float translateY = totalTranslateY + movedDistanceY; // Primero se realiza la escalada de la imagen según la proporción de escala existente matrix.postScale(totalRatio, totalRatio); // se realiza el desplazamiento según la distancia de desplazamiento matrix.postTranslate(translateX, translateY); totalTranslateX = translateX; totalTranslateY = translateY; canvas.drawBitmap(sourceBitmap, matrix, null); } /** * Se realizan operaciones de inicialización de la imagen, incluyendo centrar la imagen y comprimir la imagen cuando la imagen es mayor que las dimensiones de la pantalla. * * @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) {}} // Cuando el ancho de la imagen es mayor que el ancho de la pantalla, comprimir la imagen en proporción para que se pueda mostrar completamente float ratio = width / (bitmapWidth * 1.0f); matrix.postScale(ratio, ratio); float translateY = (height - (bitmapHeight * ratio)) / 2f; // Desplazarse en el eje Y para asegurar que la imagen se muestre al centro matrix.postTranslate(0, translateY); totalTranslateY = translateY; totalRatio = initRatio = ratio; } else { // Cuando la altura de la imagen es mayor que la altura de la pantalla, comprimir la imagen en proporción para que se pueda mostrar completamente float ratio = height / (bitmapHeight * 1.0f); matrix.postScale(ratio, ratio); float translateX = (width - (bitmapWidth * ratio)) / 2f; // Desplazarse en el eje X para asegurar que la imagen se muestre al centro matrix.postTranslate(translateX, 0); totalTranslateX = translateX; totalRatio = initRatio = ratio; } currentBitmapWidth = bitmapWidth * initRatio; currentBitmapHeight = bitmapHeight * initRatio; } else { // Cuando el ancho y el alto de la imagen son menores que el ancho y el alto de la pantalla, muestra directamente la imagen al centro 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); } } /** * Calcular la distancia entre los dos dedos. * * @param event * @return La distancia entre los dos dedos */ @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); } /** * Calcular las coordenadas del punto central entre los dos dedos. * * @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; } }
Llamada en el diseño
Lo mencionado anteriormente es el código de implementación de la ampliación y el desplazamiento de la imagen a través de un control de ImageView personalizado en Android que el editor le presenta a todos. Espero que sea útil para todos. Si tiene alguna pregunta, déjeme un mensaje y el editor responderá a tiempo. También agradezco mucho el apoyo de todos a la página web de tutorial de gritos!
Declaración: El contenido de este artículo se obtiene de la red, es propiedad del autor original, el contenido se contribuye y carga de manera autónoma por los usuarios de Internet, este sitio no posee los derechos de propiedad, no se ha procesado editorialmente y no asume ninguna responsabilidad legal relacionada. Si encuentra contenido sospechoso de infracción de derechos de autor, por favor envíe un correo electrónico a: notice#oldtoolbag.com (al enviar un correo electrónico, por favor reemplace # con @) para denunciar, y proporcione evidencia relevante. Una vez confirmado, este sitio eliminará inmediatamente el contenido sospechoso de infracción.