采用Matrix实现图片查看
来源:互联网 发布:agv磁条算法 编辑:程序博客网 时间:2024/06/05 20:41
本文是采用重写ImgView实现图片放大,缩放,移动,裁剪,
package com.example.app.view;import android.content.Context;import android.graphics.Matrix;import android.graphics.RectF;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.ScaleGestureDetector;import android.view.View;import android.view.ViewConfiguration;import android.view.ViewTreeObserver;import android.widget.ImageView;/** * Created by User on 2015/12/13. */public class ZoomImageView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener, ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener { private boolean mOnce = false; /** * 初始化时缩放的值 */ private float mInitScale; //private float minInitScale; /** * 双击放大值到达的值 */ private float mMidScale; /** * 放大的大值到达的值 */ private float mMaxScale; /** * 捕获用户多指触控是缩放的比例 */ private ScaleGestureDetector scaleGestureDetector; private Matrix mScaleMatrix; //----------自由移动 /** * 记录上一次多点触控的数量 */ private int mLastPointerCount; private float mLastX; private float mLastY; private int mTouchSlop; private boolean isCanDrag; private RectF matrixRectF; private boolean isCheckLeftAndRight; private boolean isCheckTopAndBottom; /** * 双击放大与缩小—————————————————————————— */ private GestureDetector mGestureDetector; private boolean isAutoScale; public ZoomImageView(Context context) { this(context, null); } public ZoomImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ZoomImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mScaleMatrix = new Matrix(); super.setScaleType(ScaleType.MATRIX); scaleGestureDetector = new ScaleGestureDetector(context, this); mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDoubleTap(MotionEvent e) { if (isAutoScale) { return true; } float x = e.getX(); float y = e.getY(); if (getScale() < mMidScale) {// mScaleMatrix.postScale(mMidScale / getScale(), mMidScale / getScale(), x, y);// setImageMatrix(mScaleMatrix); postDelayed(new AutoScaleRunnable(mMidScale, x, y), 16); isAutoScale = true; } else {// mScaleMatrix.postScale(mInitScale / getScale(), mInitScale / getScale(), x, y);// setImageMatrix(mScaleMatrix); postDelayed(new AutoScaleRunnable(mInitScale, x, y), 16); isAutoScale = true; } return true; } }); this.setOnTouchListener(this); //判断是否是移动 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } private class AutoScaleRunnable implements Runnable { /** * 缩放的目标 */ private float mTargetScale; //缩放的中心 private float x; private float y; private final float BIGGER = 1.07f; private final float SMALL = 0.93f; private float tmpScale; public AutoScaleRunnable(float mTargetScale, float x, float y) { this.mTargetScale = mTargetScale; this.x = x; this.y = y; if (getScale() < mTargetScale) { tmpScale = BIGGER; } if (getScale() > mTargetScale) { tmpScale = SMALL; } } @Override public void run() { //进行缩放 mScaleMatrix.postScale(tmpScale, tmpScale, x, y); ckecheBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); float currentScale = getScale(); if ((tmpScale > 1.0f && currentScale < mTargetScale) || (tmpScale < 1.0f && currentScale > mTargetScale)) { postDelayed(this, 16); } else { //设置为目标值 float scale = mTargetScale / currentScale; mScaleMatrix.postScale(scale, scale, x, y); ckecheBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); isAutoScale = false; } } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); //添加 getViewTreeObserver().addOnGlobalLayoutListener(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); //删除 getViewTreeObserver().removeGlobalOnLayoutListener(this); } /** * 获取ImageView加载完成的图片 */ @Override public void onGlobalLayout() { if (!mOnce) { //得到控件的宽和高 int width = getWidth(); int height = getHeight(); //得到我们的图片,以及宽和高 Drawable drawable = getDrawable(); if (drawable == null) { return; } int drawableWidth = drawable.getIntrinsicWidth(); int drawableHeight = drawable.getIntrinsicHeight(); float scale = 1.0f; float minScale = 1.0f; /** * 如果图片的宽度大于控件宽度,但是高度小于控件宽度,我们将其放大、 * */ if (drawableWidth > width && drawableHeight < height) { scale = width * 1.0f / drawableWidth; } /** * 如果图片的高度于控件高度,但是宽度小于控件宽度,我们将其缩小、 * */ if (drawableHeight > height && drawableWidth < width) { scale = height * 1.0f / drawableHeight; } /** * 如果图片的宽高都大于控件,我们将其缩小,。 * */ if (drawableWidth > width && drawableHeight > height) { scale = Math.min(width * 1.0f / drawableWidth, height * 1.0f / drawableHeight); } /** * 如果图片的宽高都小于控件,我们将其放大。 * */ if (drawableWidth < width && drawableHeight < height) { scale = Math.min(width * 1.0f / drawableWidth, height * 1.0f / drawableHeight); } /** * 得到了初始化时缩放的比例 * */ mInitScale = scale; mMaxScale = mInitScale * 4; mMidScale = mInitScale * 2; // minInitScale = minScale; mOnce = true; /** * 将图片移动至控件的中心 * */ int dx = getWidth() / 2 - drawableWidth / 2; int dy = getHeight() / 2 - drawableHeight / 2; mScaleMatrix.postTranslate(dx, dy); mScaleMatrix.postScale(mInitScale, mInitScale, width / 2, height / 2); setImageMatrix(mScaleMatrix); } } //缩放的区间:initScale,MaxScale //获取图片当前的缩放值 public float getScale() { float[] values = new float[9]; mScaleMatrix.getValues(values); return values[Matrix.MSCALE_X]; } @Override public boolean onScale(ScaleGestureDetector detector) { float scale = getScale(); //获得当前的缩放值 float scaleFactor = detector.getScaleFactor(); Log.d("scaleFactor", ":" + scaleFactor); if (getDrawable() == null) { return true; } //缩放范围的控制 if ((scale < mMaxScale && scaleFactor > 1.0f) || (scale > mInitScale && scaleFactor < 1.0f)) { if (scale * scaleFactor < mInitScale) { scaleFactor = mInitScale / scale; } if (scale * scaleFactor > mMaxScale) { scaleFactor = mMaxScale / scale; } mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY()); ckecheBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); } return true; } /** * 获得图片放大缩小以后的宽和高,以及l,r,t,b */ private RectF getMatrixRectF() { Matrix rMatrix = mScaleMatrix; RectF rectF = new RectF(); Drawable d = getDrawable(); if (d != null) { rectF.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); rMatrix.mapRect(rectF); } return rectF; } /** * 再缩放的时候进行边界控制已经我们的位置的控制 */ private void ckecheBorderAndCenterWhenScale() { RectF rect = getMatrixRectF(); float deltaX = 0; float deltaY = 0; int width = getWidth(); int height = getHeight(); if (rect.width() >= width) { if (rect.left > 0) { deltaX = -rect.left; } if (rect.right < width) { deltaX = width - rect.right; } } if (rect.height() >= height) { if (rect.top > 0) { deltaY = -rect.top; } if (rect.bottom < height) { deltaY = height - rect.bottom; } } /** * 如果宽度或者高度小于控件的宽或者高;则让其居中 * * */ if (rect.width() < width) { deltaX = width * 0.5f - rect.right + 0.5f * rect.width(); } if (rect.height() < height) { deltaY = height * 0.5f - rect.bottom + 0.5f * rect.height(); } mScaleMatrix.postTranslate(deltaX, deltaY); } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { } @Override public boolean onTouch(View v, MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) { return true; } scaleGestureDetector.onTouchEvent(event); float X = 0; float Y = 0; /** * 拿到多点触控的数量 * */ int pointerCount = event.getPointerCount(); for (int i = 0; i < pointerCount; i++) { X += event.getX(i); Y += event.getY(i); } X /= pointerCount; Y /= pointerCount; if (mLastPointerCount != pointerCount) { mLastX = X; mLastY = Y; } mLastPointerCount = pointerCount; switch (event.getAction()) { case MotionEvent.ACTION_MOVE: float dx = X - mLastX; float dy = Y - mLastY; if (!isCanDrag) { isCanDrag = isMoveAction(dx, dy); } if (isCanDrag) { RectF rectF = getMatrixRectF(); if (getDrawable() != null) { isCheckLeftAndRight = isCheckTopAndBottom = true; /** * 如果宽度小于控件宽度,不允许横向移动 * */ if (rectF.width() < getWidth()) { isCheckLeftAndRight = false; dx = 0; } /** * 如果高度小于控件高度,不允许纵向移动 * */ if (rectF.height() < getHeight()) { isCheckTopAndBottom = false; dy = 0; } mScaleMatrix.postTranslate(dx, dy); checkBorderWhenTranslate(); setImageMatrix(mScaleMatrix); } } mLastX = X; mLastY = Y; break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mLastPointerCount = 0; break; } return true; } /** * 当移动,进行边界检查 */ private void checkBorderWhenTranslate() { RectF rectF = getMatrixRectF(); float deltaX = 0; float deltaY = 0; int width = getWidth(); int height = getHeight(); if (rectF.top > 0 && isCheckTopAndBottom) { deltaY = -rectF.top; } if (rectF.bottom < height && isCheckTopAndBottom) { deltaY = height - rectF.bottom; } if (rectF.left > 0 && isCheckLeftAndRight) { deltaX = -rectF.left; } if (rectF.right < width && isCheckLeftAndRight) { deltaX = width - rectF.right; } mScaleMatrix.postTranslate(deltaX, deltaY); } /** * 判断是否是Move */ private boolean isMoveAction(float dx, float dy) { return Math.sqrt(dx * dx + dy * dy) > mTouchS } /** * 剪切图片,返回剪切后的bitmap对象 圆形用 * * @return */ public Bitmap clip() { Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); int yStartPoint = DensityUtils.dp2px(getContext(), (float) 135.333); int xStartPoint = DensityUtils.dp2px(getContext(), (float) 62); int circleRadius = DensityUtils.dp2px(getContext(), (float) 236); draw(canvas); return Bitmap.createBitmap(bitmap, xStartPoint, yStartPoint, circleRadius, circleRadius); }}
0 0
- 采用Matrix实现图片查看
- Android 利用Matrix实现图片的缩放查看
- 实现查看图片
- 采用handle 实现下载图片带有进度条
- Matrix图片
- android实现翻页查看图片
- ViewDragHelper实现相册图片查看
- 实现查看网络图片功能
- 实现查看网络图片功能
- canvas实现放大镜查看图片
- svm应用范例,采用svm实现图片的分…
- 采用Python实现自动发送摄像头图片到微博
- 实现下载图片显示进度条(采用asynctask)
- 单片机采用RLE算法实现液晶屏显示图片
- 轮播器(三)--采用UICollectionView实现图片无限轮播
- Android开发--Matrix(二)--实现图片的旋转
- 触摸事件+矩阵Matrix实现图片的拖拉缩放
- Android中利用Matrix实现图片平移、缩放和旋转
- webservice cxf 拦截器
- 先验概率与后验概率、贝叶斯区别与联系
- Android 网络编程基础
- oracle pl/sql 分隔逗号
- hdu1512
- 采用Matrix实现图片查看
- 网页前端开发经常会逛到的网站
- install ndnSIM on Ubuntu 14.04
- iOS framework 合成
- Java中static与final的思考
- cocos2d-x使用tinyxml2解析&存储xml
- #git常用命令
- Suggestion: add 'tools:replace="android:icon"' to <application> element at AndroidManifest.xml
- expr用法