使用 Matrix 的随触摸旋转的ImageView
突然想做个 类似 旋转开关的东西。然后就用了surfaceView做了个一个。
快做完的时候 朋友说道可以使用imageView来实现我想要的效果,然后就研究了下。
几个keypoint点
1.需要设置setScaleType(ScaleType.MATRIX);
2.matrix 需要new出来 通过getImageMatrix()的不行
3.通过setImageMatrix() 会调用invalidate() 从而重绘。
另外:
Matrix的
postRotate与setRotate
postRotate会基于Matrix上次的矩阵旋转
而setRotate会重置矩阵然后旋转
注:可延伸至Matrix 的postXX setXX
普通旋转:
iv 为imageView对象。
Matrix m=new Matrix();
m.postRotate(30f,iv.getWidth()/2,iv.getHeight()/2);
iv.setImageMatrix(m);
代码如下:
package com.lurencun.poolotools.ui.light; import android.content.Context; import android.graphics.Canvas; import android.graphics.Matrix; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.ImageView; /** * 随触摸旋转ImageView * * @author liupoolo * @since 2013-02-22 * @version 1.00 */ public class TouchRoateImageView extends ImageView { private final static float MIN_DEGREE = 0f; private final static float MAX_DEGREE = 360f; private Matrix m; private float saveX; // 当前保存的x private float saveY; // 当前保存的y private float curTouchX; // 当前触屏的x private float curTouchY; // 当前触摸的y private float centerX; // 中心点x private float centerY; // 中心点y private float curDegree; // 当前角度 private float changeDegree; public TouchRoateImageView(Context context, AttributeSet attrs) { super(context, attrs); setScaleType(ScaleType.MATRIX);// 重点 m = new Matrix(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); centerX = this.getWidth() / 2; centerY = this.getHeight() / 2; } public boolean onTouchEvent(MotionEvent event) { handleTouch(event); return true; } private void handleTouch(MotionEvent event) { curTouchX = event.getX(); curTouchY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: saveTouchPoint(); break; case MotionEvent.ACTION_MOVE: handleTouchMove(); break; case MotionEvent.ACTION_UP: // 可以使用访问者模式这里让访问者获得当前角度 break; } } private void handleTouchMove() { changeDegree = (float) getActionDegrees(centerX, centerY, saveX, saveY, curTouchX, curTouchY); float tempDegree = (float) curDegree + changeDegree; if (tempDegree >= MIN_DEGREE && tempDegree <= MAX_DEGREE) { optimize(tempDegree);//优化变动 m.setRotate(curDegree, centerX, centerY); setImageMatrix(m);// 此方法会 调用invalidate() 从而重绘界面 } saveTouchPoint(); } private void optimize(float tempDegree){ if(tempDegree>MAX_DEGREE-1){ curDegree=MAX_DEGREE; }else if(tempDegree<MIN_DEGREE+1){ curDegree=MIN_DEGREE; }else{ this.curDegree = tempDegree; } } private void saveTouchPoint() { saveX = curTouchX; saveY = curTouchY; } /** * 获取两点到第三点的夹角。 * * @param x * @param y * @param x1 * @param y1 * @param x2 * @param y2 * @return */ private double getActionDegrees(float x, float y, float x1, float y1, float x2, float y2) { double a = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); double b = Math.sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2)); double c = Math.sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)); // 余弦定理 double cosA = (b * b + c * c - a * a) / (2 * b * c); // 返回余弦值为指定数字的角度,Math函数为我们提供的方法 double arcA = Math.acos(cosA); double degree = arcA * 180 / Math.PI; // 接下来我们要讨论正负值的关系了,也就是求出是顺时针还是逆时针。 // 第1、2象限 if (y1 < y && y2 < y) { if (x1 < x && x2 > x) {// 由2象限向1象限滑动 return degree; } // 由1象限向2象限滑动 else if (x1 >= x && x2 <= x) { return -degree; } } // 第3、4象限 if (y1 > y && y2 > y) { // 由3象限向4象限滑动 if (x1 < x && x2 > x) { return -degree; } // 由4象限向3象限滑动 else if (x1 > x && x2 < x) { return degree; } } // 第2、3象限 if (x1 < x && x2 < x) { // 由2象限向3象限滑动 if (y1 < y && y2 > y) { return -degree; } // 由3象限向2象限滑动 else if (y1 > y && y2 < y) { return degree; } } // 第1、4象限 if (x1 > x && x2 > x) { // 由4向1滑动 if (y1 > y && y2 < y) { return -degree; } // 由1向4滑动 else if (y1 < y && y2 > y) { return degree; } } // 在特定的象限内 float tanB = (y1 - y) / (x1 - x); float tanC = (y2 - y) / (x2 - x); if ((x1 > x && y1 > y && x2 > x && y2 > y && tanB > tanC)// 第一象限 || (x1 > x && y1 < y && x2 > x && y2 < y && tanB > tanC)// 第四象限 || (x1 < x && y1 < y && x2 < x && y2 < y && tanB > tanC)// 第三象限 || (x1 < x && y1 > y && x2 < x && y2 > y && tanB > tanC))// 第二象限 return -degree; return degree; } public float getCurDegree() { return curDegree; } public void setCurDegree(float curDegree) { if (curDegree >= MIN_DEGREE && curDegree <= MAX_DEGREE) { this.curDegree = curDegree; m.setRotate(curDegree, centerX, centerY); setImageMatrix(m); } } }
相关推荐
android 动态旋转图片 Bitmap与Matrix旋转ImageView
android自定义ImageView实现旋转动画
在Android中进行图像旋转需要使用Matrix,它包含了一个3*3的矩阵,专门用于进行图像变换匹配。Matrix ,中文里叫矩阵,高等数学里有介绍,在图像处理方面,主要是用于平面的缩放、平移、旋转等操作。Matrix没有机构...
Android、Matrix、ImageView、Bitmap结合使用
主要介绍了Android使用RotateImageView 旋转ImageView 的相关资料,需要的朋友可以参考下
progress-image-view-android 带简单进度的android ImageView控件
Android 自定义MutiTouchImageView (移动、缩放、旋转)
主要是使用了ImageView和AnimationDrawable组合的方式来实现ProgressBar的旋转效果
可以旋转的ImageView
RCImageView 自定义圆角ImageView,带边框效果
android 自定义属性实现 ImageView 透明度渐变效果
ANDROID,实现imageview的各种操作,手势放大,缩小,旋转等
AndroidImageView控件缩放和旋转图片源码.zip
Android开发之ImageView通过matrix实现两点缩放和图片拖动,内有较为详细的注释
ImageView 图片显示样式的几种类型。android:scaleType是控制图片如何resized/moved来匹对ImageView的size。
Android ImageViewEx 支持Gif显示的ImageView Demo.zip
android自定义ImageView,圆角和圆形,抗锯齿.亲测可用。直接拷贝代码就行。
android ImageView控件缩放和旋转图片源码.rar
Android 使用animation_list 实现imageview 动画效果
源码参考,欢迎下载