android+图片查看器自适应,[转载]android 图片查看器,可通过多点触控实现缩放...

该博客介绍了如何在Android中定制一个ImageView,支持缩放、平移功能,并利用键盘控制。通过设置Matrix和监听键盘事件,实现了图片的精细调整和用户交互。关键代码展示了如何计算适应屏幕的缩放比例,以及使用Handler进行动画效果的控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.lyc.pic;

import java.io.InputStream;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Matrix;

import android.graphics.RectF;

import android.os.Handler;

import android.util.AttributeSet;

import android.util.Log;

import android.view.KeyEvent;

import android.widget.ImageView;

public class MyImageView extends ImageView {

@SuppressWarnings("unused")

private static final String TAG = "ImageViewTouchBase";

protected Matrix mBaseMatrix = new Matrix();

protected Matrix mSuppMatrix = new Matrix();

private final Matrix mDisplayMatrix = new Matrix();

private final float[] mMatrixValues = new float[9];

// The current bitmap being displayed.

// protected final RotateBitmap mBitmapDisplayed = new

RotateBitmap(null);

protected Bitmap image = null;

int mThisWidth = -1, mThisHeight = -1;

float mMaxZoom = 2.0f;// 最大缩放比例

float mMinZoom ;// 最小缩放比例

private int imageWidth;// 图片的原始宽度

private int imageHeight;// 图片的原始高度

private float scaleRate;// 图片适应屏幕的缩放比例

protected void onDraw(Canvas canvas) {

//正在显示的图片实际宽高

float width = imageWidth*getScale();

float height = imageHeight*getScale();

if (width > MianActivity.screenWidth) {

// 如果图宽大于屏宽,就不用水平居中

center(false, true);

} else {

center(true, true);

}

super.onDraw(canvas);

}

public MyImageView(Context context, int imageWidth, int

imageHeight) {

super(context);

this.imageHeight = imageHeight;

this.imageWidth = imageWidth;

init();

}

public MyImageView(Context context, AttributeSet attrs, int

imageWidth, int imageHeight) {

super(context, attrs);

this.imageHeight = imageHeight;

this.imageWidth = imageWidth;

init();

}

private void arithScaleRate() {

float scaleWidth = MianActivity.screenWidth / (float)

imageWidth;

float scaleHeight = MianActivity.screenHeight / (float)

imageHeight;

scaleRate = Math.min(scaleWidth, scaleHeight);

}

public float getScaleRate() {

return scaleRate;

}

public int getImageWidth() {

return imageWidth;

}

public void setImageWidth(int imageWidth) {

this.imageWidth = imageWidth;

}

public int getImageHeight() {

return imageHeight;

}

public void setImageHeight(int imageHeight) {

this.imageHeight = imageHeight;

}

@Override

public boolean onKeyDown(int keyCode, KeyEvent event) {

if (keyCode == KeyEvent.KEYCODE_BACK

&& event.getRepeatCount() == 0)

{

event.startTracking();

return true;

}

return super.onKeyDown(keyCode, event);

}

@Override

public boolean onKeyUp(int keyCode, KeyEvent event) {

if (keyCode == KeyEvent.KEYCODE_BACK

&& event.isTracking()

&& !event.isCanceled()) {

if (getScale() > 1.0f) {

// If we're zoomed in, pressing Back jumps out to show

the

// entire image, otherwise Back returns the user to the

gallery.

zoomTo(1.0f);

return true;

}

}

return super.onKeyUp(keyCode, event);

}

protected Handler mHandler = new Handler();

@Override

public void setImageBitmap(Bitmap bitmap) {

super.setImageBitmap(bitmap);

image = bitmap;

// 计算适应屏幕的比例

arithScaleRate();

//缩放到屏幕大小

zoomTo(scaleRate,MianActivity.screenWidth / 2f,

MianActivity.screenHeight / 2f);

//居中

layoutToCenter();

}

protected void center(boolean horizontal, boolean vertical)

{

if (image == null) {

return;

}

Matrix m = getImageViewMatrix();

RectF rect = new RectF(0, 0, image.getWidth(),

image.getHeight());

m.mapRect(rect);

float height = rect.height();

float width = rect.width();

float deltaX = 0, deltaY = 0;

if (vertical) {

int viewHeight = getHeight();

if (height < viewHeight) {

deltaY = (viewHeight - height) / 2 - rect.top;

} else if (rect.top > 0) {

deltaY = -rect.top;

} else if (rect.bottom < viewHeight) {

deltaY = getHeight() - rect.bottom;

}

}

if (horizontal) {

int viewWidth = getWidth();

if (width < viewWidth) {

deltaX = (viewWidth - width) / 2 - rect.left;

} else if (rect.left > 0) {

deltaX = -rect.left;

} else if (rect.right < viewWidth) {

deltaX = viewWidth - rect.right;

}

}

postTranslate(deltaX, deltaY);

setImageMatrix(getImageViewMatrix());

}

private void init() {

setScaleType(ImageView.ScaleType.MATRIX);

}

public void layoutToCenter()

{

//正在显示的图片实际宽高

float width = imageWidth*getScale();

float height = imageHeight*getScale();

//空白区域宽高

float fill_width = MianActivity.screenWidth - width;

float fill_height = MianActivity.screenHeight - height;

//需要移动的距离

float tran_width = 0f;

float tran_height = 0f;

if(fill_width>0)

tran_width = fill_width/2;

if(fill_height>0)

tran_height = fill_height/2;

postTranslate(tran_width, tran_height);

setImageMatrix(getImageViewMatrix());

}

protected float getValue(Matrix matrix, int whichValue)

{

matrix.getValues(mMatrixValues);

mMinZoom =( MianActivity.screenWidth/2f)/imageWidth;

return mMatrixValues[whichValue];

}

// Get the scale factor out of the matrix.

protected float getScale(Matrix matrix) {

return getValue(matrix, Matrix.MSCALE_X);

}

protected float getScale() {

return getScale(mSuppMatrix);

}

// Combine the base matrix and the supp matrix to make the

final matrix.

protected Matrix getImageViewMatrix() {

// The final matrix is computed as the concatentation of the

base matrix

// and the supplementary matrix.

mDisplayMatrix.set(mBaseMatrix);

mDisplayMatrix.postConcat(mSuppMatrix);

return mDisplayMatrix;

}

static final float SCALE_RATE = 1.25F;

// Sets the maximum zoom, which is a scale relative to the

base matrix. It

// is calculated to show the image at 400% zoom regardless of

screen or

// image orientation. If in the future we decode the full 3

megapixel image,

// rather than the current 1024x768, this should be changed

down to 200%.

protected float maxZoom() {

if (image == null) {

return 1F;

}

float fw = (float) image.getWidth() / (float)

mThisWidth;

float fh = (float) image.getHeight() / (float)

mThisHeight;

float max = Math.max(fw, fh) * 4;

return max;

}

protected void zoomTo(float scale, float centerX, float

centerY) {

if (scale > mMaxZoom) {

scale = mMaxZoom;

} else if (scale < mMinZoom) {

scale = mMinZoom;

}

float oldScale = getScale();

float deltaScale = scale / oldScale;

mSuppMatrix.postScale(deltaScale, deltaScale, centerX,

centerY);

setImageMatrix(getImageViewMatrix());

center(true, true);

}

protected void zoomTo(final float scale, final float centerX,

final float centerY, final float durationMs) {

final float incrementPerMs = (scale - getScale()) /

durationMs;

final float oldScale = getScale();

final long startTime = System.currentTimeMillis();

mHandler.post(new Runnable() {

public void run() {

long now = System.currentTimeMillis();

float currentMs = Math.min(durationMs, now - startTime);

float target = oldScale + (incrementPerMs * currentMs);

zoomTo(target, centerX, centerY);

if (currentMs < durationMs) {

mHandler.post(this);

}

}

});

}

protected void zoomTo(float scale) {

float cx = getWidth() / 2F;

float cy = getHeight() / 2F;

zoomTo(scale, cx, cy);

}

protected void zoomToPoint(float scale, float pointX, float

pointY) {

float cx = getWidth() / 2F;

float cy = getHeight() / 2F;

panBy(cx - pointX, cy - pointY);

zoomTo(scale, cx, cy);

}

protected void zoomIn() {

zoomIn(SCALE_RATE);

}

protected void zoomOut() {

zoomOut(SCALE_RATE);

}

protected void zoomIn(float rate) {

if (getScale() >= mMaxZoom) {

return; // Don't let the user zoom into the molecular

level.

} else if (getScale() <= mMinZoom) {

return;

}

if (image == null) {

return;

}

float cx = getWidth() / 2F;

float cy = getHeight() / 2F;

mSuppMatrix.postScale(rate, rate, cx, cy);

setImageMatrix(getImageViewMatrix());

}

protected void zoomOut(float rate) {

if (image == null) {

return;

}

float cx = getWidth() / 2F;

float cy = getHeight() / 2F;

// Zoom out to at most 1x.

Matrix tmp = new Matrix(mSuppMatrix);

tmp.postScale(1F / rate, 1F / rate, cx, cy);

if (getScale(tmp) < 1F) {

mSuppMatrix.setScale(1F, 1F, cx, cy);

} else {

mSuppMatrix.postScale(1F / rate, 1F / rate, cx, cy);

}

setImageMatrix(getImageViewMatrix());

center(true, true);

}

public void postTranslate(float dx, float dy) {

mSuppMatrix.postTranslate(dx, dy);

setImageMatrix(getImageViewMatrix());

}

float _dy=0.0f;

protected void postTranslateDur( final float dy, final float

durationMs) {

_dy=0.0f;

final float incrementPerMs = dy / durationMs;

final long startTime = System.currentTimeMillis();

mHandler.post(new Runnable() {

public void run() {

long now = System.currentTimeMillis();

float currentMs = Math.min(durationMs, now - startTime);

postTranslate(0, incrementPerMs*currentMs-_dy);

_dy=incrementPerMs*currentMs;

if (currentMs < durationMs) {

mHandler.post(this);

}

}

});

}

protected void panBy(float dx, float dy) {

postTranslate(dx, dy);

setImageMatrix(getImageViewMatrix());

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值