1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 安卓图片手势缩放 旋转 移动

安卓图片手势缩放 旋转 移动

时间:2019-10-06 18:33:18

相关推荐

安卓图片手势缩放 旋转 移动

两个ImageView都可以手势缩放、旋转、移动

自定义ImageView一

import android.content.Context;import android.graphics.Matrix;import android.graphics.RectF;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.ScaleGestureDetector;import android.view.View;import android.view.ViewTreeObserver;import androidx.appcompat.widget.AppCompatImageView;public class MyImageView extends AppCompatImageView implements ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener {/*** 控件宽度*/private int mWidth;/*** 控件高度*/private int mHeight;/*** 拿到src的图片*/private Drawable mDrawable;/*** 图片宽度(使用前判断mDrawable是否null)*/private int mDrawableWidth;/*** 图片高度(使用前判断mDrawable是否null)*/private int mDrawableHeight;/*** 初始化缩放值*/private float mScale;/*** 双击图片的缩放值*/private float mDoubleClickScale;/*** 最大的缩放值*/private float mMaxScale;/*** 最小的缩放值*/private float mMinScale;private ScaleGestureDetector scaleGestureDetector;/*** 当前有着缩放值、平移值的矩阵。*/private Matrix matrix;public MyImageView(Context context) {this(context, null);}public MyImageView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);setOnTouchListener(this);scaleGestureDetector = new ScaleGestureDetector(context, this);initListener();}/*** 初始化事件监听*/private void initListener() {// 强制设置模式setScaleType(ScaleType.MATRIX);// 添加观察者getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {// 移除观察者getViewTreeObserver().removeGlobalOnLayoutListener(this);// 获取控件大小mWidth = getWidth();mHeight = getHeight();//通过getDrawable获得Src的图片mDrawable = getDrawable();if (mDrawable == null)return;mDrawableWidth = mDrawable.getIntrinsicWidth();mDrawableHeight = mDrawable.getIntrinsicHeight();initImageViewSize();//moveToCenter();}});}/*** 初始化资源图片宽高*/private void initImageViewSize() {if (mDrawable == null)return;// 缩放值float scale = 0.5f;/*// 图片宽度大于控件宽度,图片高度小于控件高度if (mDrawableWidth > mWidth && mDrawableHeight < mHeight)scale = mWidth * scale / mDrawableWidth;// 图片高度度大于控件宽高,图片宽度小于控件宽度else if (mDrawableHeight > mHeight && mDrawableWidth < mWidth)scale = mHeight * scale / mDrawableHeight;// 图片宽度大于控件宽度,图片高度大于控件高度else if (mDrawableHeight > mHeight && mDrawableWidth > mWidth)scale = Math.min(mHeight * scale / mDrawableHeight, mWidth * scale / mDrawableWidth);// 图片宽度小于控件宽度,图片高度小于控件高度else if (mDrawableHeight < mHeight && mDrawableWidth < mWidth)scale = Math.min(mHeight * scale / mDrawableHeight, mWidth * scale / mDrawableWidth);*/mScale = scale;mMaxScale = mScale * 8.0f;mMinScale = mScale * 0.1f;}/*** 移动控件中间位置*/private void moveToCenter() {final float dx = mWidth / 2 ;final float dy = mHeight / 2;//final float dx = mWidth / 2 - mDrawableWidth / 2;//final float dy = mHeight / 2 - mDrawableHeight / 2;matrix = new Matrix();// 平移至中心matrix.postTranslate(dx, dy);// 以控件中心作为缩放matrix.postScale(mScale, mScale, mWidth / 2, mHeight / 2);setImageMatrix(matrix);}/*** @return 当前缩放的值*/private float getmScale() {float[] floats = new float[9];matrix.getValues(floats);return floats[Matrix.MSCALE_X];}/*** @param matrix 矩阵* @return matrix的 l t b r 和width,height*/private RectF getRectf(Matrix matrix) {RectF f = new RectF();if (mDrawable == null)return null;f.set(0, 0, mDrawableWidth, mDrawableHeight);matrix.mapRect(f);return f;}@Overridepublic boolean onScale(ScaleGestureDetector detector) {if (mDrawable == null) {return true;}// 系统定义的缩放值float scaleFactor = detector.getScaleFactor();// 获取已经缩放的值float scale = getmScale();float scaleResult = scale * scaleFactor;if (scaleResult >= mMaxScale && scaleFactor > 1.0f)scaleFactor = mMaxScale / scale;if (scaleResult <= mMinScale && scaleFactor < 1.0f)scaleFactor = mMinScale / scale;matrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());RectF f = getRectf(matrix);float dX = 0.0f;float dY = 0.0f;// 图片高度大于控件高度if (f.height() >= mHeight) {// 图片顶部出现空白if (f.top > 0) {// 往上移动dY = -f.top;}// 图片底部出现空白if (f.bottom < mHeight) {// 往下移动dY = mHeight - f.bottom;}}// 图片宽度大于控件宽度if (f.width() >= mWidth) {// 图片左边出现空白if (f.left > 0) {// 往左边移动dX = -f.left;}// 图片右边出现空白if (f.right < mWidth) {// 往右边移动dX = mWidth - f.right;}}if (f.width() < mWidth) {dX = mWidth / 2 - f.right + f.width() / 2;}if (f.height() < mHeight) {dY = mHeight / 2 - f.bottom + f.height() / 2;}matrix.postTranslate(dX, dY);setImageMatrix(matrix);return true;}@Overridepublic boolean onScaleBegin(ScaleGestureDetector detector) {return true;}@Overridepublic void onScaleEnd(ScaleGestureDetector detector) {float scale = getmScale();if (scale < mScale) {matrix.postScale(mScale / scale, mScale / scale, mWidth / 2, mHeight / 2);setImageMatrix(matrix);}}private float downX;private float downY;private float nowMovingX;private float nowMovingY;private float lastMovedX;private float lastMovedY;private boolean isFirstMoved = false;@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction() & MotionEvent.ACTION_MASK) {case MotionEvent.ACTION_DOWN:isFirstMoved = false;downX = event.getX();downY = event.getY();break;case MotionEvent.ACTION_POINTER_DOWN:isFirstMoved = false;break;case MotionEvent.ACTION_MOVE:nowMovingX = event.getX();nowMovingY = event.getY();if (!isFirstMoved) {isFirstMoved = true;lastMovedX = nowMovingX;lastMovedY = nowMovingY;}float dX = 0.0f;float dY = 0.0f;RectF rectf = getRectf(matrix);// 判断滑动方向final float scrollX = nowMovingX - lastMovedX;// 判断滑动方向final float scrollY = nowMovingY - lastMovedY;// 图片高度大于控件高度if (rectf.height() > mHeight && canSmoothY()) {dY = nowMovingY - lastMovedY;}// 图片宽度大于控件宽度if (rectf.width() > mWidth && canSmoothX()) {dX = nowMovingX - lastMovedX;}matrix.postTranslate(dX, dY);remedyXAndY(dX,dY);lastMovedX = nowMovingX;lastMovedY = nowMovingY;break;case MotionEvent.ACTION_UP:break;case MotionEvent.ACTION_POINTER_UP:isFirstMoved = false;break;}return scaleGestureDetector.onTouchEvent(event);}/*** 判断x方向上能不能滑动* @return 可以滑动返回true*/private boolean canSmoothX(){RectF rectf = getRectf(matrix);if (rectf.left >0 || rectf.right <getWidth())return false;return true;}/*** 判断y方向上可不可以滑动* @return 可以滑动返回true*/private boolean canSmoothY(){RectF rectf = getRectf(matrix);if (rectf.top>0 || rectf.bottom < getHeight())return false;return true;}/*** 纠正出界的横和众线* @param dx 出界偏移的横线* @param dy 出街便宜的众线*/private void remedyXAndY(float dx,float dy){if (!canSmoothX())matrix.postTranslate(-dx,0);if (!canSmoothY())matrix.postTranslate(0,-dy);setImageMatrix(matrix);}}

自定义ImageView二

import android.content.Context;import android.graphics.Matrix;import android.graphics.PointF;import android.util.AttributeSet;import android.view.MotionEvent;import androidx.appcompat.widget.AppCompatImageView;public class TouchImageView extends AppCompatImageView {private PointF startPoint = new PointF();private Matrix matrix = new Matrix();private Matrix currentMaritx = new Matrix();PointF mid = new PointF();private int mode = 0;//用于标记模式private static final int DRAG = 1;//拖动private static final int ZOOM = 2;//放大private float startDis = 0;private PointF midPoint;//中心点float oldRotation = 0;public TouchImageView(Context context){super(context);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {super.onLayout(changed, left, top, right, bottom);}public TouchImageView(Context context,AttributeSet paramAttributeSet){super(context,paramAttributeSet);}public boolean onTouchEvent(MotionEvent event) {switch (event.getAction() & MotionEvent.ACTION_MASK) {case MotionEvent.ACTION_DOWN:mode = DRAG;currentMaritx.set(this.getImageMatrix());//记录ImageView当期的移动位置startPoint.set(event.getX(),event.getY());//开始点break;case MotionEvent.ACTION_MOVE://移动事件if (mode == DRAG) {//图片拖动事件float dx = event.getX() - startPoint.x;//x轴移动距离float dy = event.getY() - startPoint.y;matrix.set(currentMaritx);//在当前的位置基础上移动matrix.postTranslate(dx, dy);} else if(mode == ZOOM){//图片放大事件float rotation = rotation(event) - oldRotation;float endDis = distance(event);//结束距离if(endDis > 10f){float scale = endDis / startDis;//放大倍数matrix.set(currentMaritx);matrix.postScale(scale, scale, midPoint.x, midPoint.y);matrix.postRotate(rotation, midPoint.x, midPoint.y);// 旋轉}}break;case MotionEvent.ACTION_UP:mode = 0;break;//有手指离开屏幕,但屏幕还有触点(手指)case MotionEvent.ACTION_POINTER_UP:mode = 0;break;//当屏幕上已经有触点(手指),再有一个手指压下屏幕case MotionEvent.ACTION_POINTER_DOWN:oldRotation = rotation(event);mode = ZOOM;startDis = distance(event);if(startDis > 10f){midPoint = mid(event);currentMaritx.set(this.getImageMatrix());//记录当前的缩放倍数}break;}this.setImageMatrix(matrix);return true;}// 取旋转角度private float rotation(MotionEvent event) {double delta_x = (event.getX(0) - event.getX(1));double delta_y = (event.getY(0) - event.getY(1));double radians = Math.atan2(delta_y, delta_x);return (float) Math.toDegrees(radians);}// 取手势中心点private void midPoint(PointF point, MotionEvent event) {float x = event.getX(0) + event.getX(1);float y = event.getY(0) + event.getY(1);point.set(x / 2, y / 2);}/*** 两点之间的距离* @param event* @return*/private static float distance(MotionEvent event){//两根线的距离float dx = event.getX(1) - event.getX(0);float dy = event.getY(1) - event.getY(0);return (float) Math.sqrt(dx*dx + dy*dy);}/*** 计算两点之间中心点的距离* @param event* @return*/private static PointF mid(MotionEvent event){float midx = event.getX(1) + event.getX(0);float midy = event.getY(1) - event.getY(0);return new PointF(midx/2, midy/2);}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。