android 图片的平移,缩放和旋转
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <!-- 定义TextView的文本标签 --> <TextView android:id="@+id/Tv" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="点击屏幕,隐藏或显示导航栏!" /> </RelativeLayout>
MyView.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | package com.example.yanlei.yl; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.PointF; import android.util.DisplayMetrics; import android.util.FloatMath; import android.view.MotionEvent; import android.widget.ImageView; //自定义MyView类继承自ImageView public class MyView extends ImageView { private float x_down = 0 ; private float y_down = 0 ; //起始点的坐标 private PointF start = new PointF(); //中心点的坐标 private PointF mid = new PointF(); private float oldDist = 1f; private float oldRotation = 0 ; private Matrix matrix = new Matrix(); private Matrix matrix1 = new Matrix(); private Matrix savedMatrix = new Matrix(); private static final int NONE = 0 ; private static final int DRAG = 1 ; private static final int ZOOM = 2 ; private int mode = NONE; private boolean matrixCheck = false ; //记录当前屏幕的宽度 private int widthScreen; //记录当前屏幕的高度 private int heightScreen; //在页面中显示的Bitmap图片 private Bitmap kenan; public MyView(Activity activity) { super (activity); //通过Bitampfactory读取drawable目录下的kenan资源 kenan = BitmapFactory. decodeResource(getResources(), R.drawable.kenan); //定义图片一个显示矩阵 DisplayMetrics dm = new DisplayMetrics(); //得到当前屏幕的显示矩阵存入dm变量 activity.getWindowManager(). getDefaultDisplay().getMetrics(dm); //通过显示矩阵得到当前屏幕的宽度和高度的像素值 widthScreen = dm.widthPixels; heightScreen = dm.heightPixels; matrix = new Matrix(); } //显示view的时候回调onDraw protected void onDraw(Canvas canvas) { //首先保存当前页面已有的图像 canvas.save(); //按照当前的矩阵绘制kenan图片 canvas.drawBitmap(kenan, matrix, null ); //画图板恢复 canvas.restore(); } //当用户触摸此视图的时候回调次方法 public boolean onTouchEvent(MotionEvent event) { //得到touch的事件类型 switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: //当按下屏幕时,记录当前的状态为拖动 mode = DRAG; //记录xy坐标 x_down = event.getX(); y_down = event.getY(); //保存当前的矩阵 savedMatrix.set(matrix); break ; case MotionEvent.ACTION_POINTER_DOWN: //多个手指触摸的状态 mode = ZOOM; //记录之前的两手指间距 oldDist = spacing(event); //记录之前的角度 oldRotation = rotation(event); //保存当前的图片矩阵 savedMatrix.set(matrix); //得到旋转的中心点 midPoint(mid, event); break ; case MotionEvent.ACTION_MOVE: //当手指移动时的状态 if (mode == ZOOM) { //缩放并且平移 matrix1.set(savedMatrix); //得到旋转的角度 float rotation = rotation(event) - oldRotation; //得到距离 float newDist = spacing(event); //得到放大倍数 float scale = newDist / oldDist; //缩放倍数 matrix1.postScale(scale, scale, mid.x, mid.y); //得到旋转角度 matrix1.postRotate(rotation, mid.x, mid.y); //得到图片是否出边界 matrixCheck = matrixCheck(); if (matrixCheck == false ) { matrix.set(matrix1); invalidate(); } } else if (mode == DRAG) { //平行移动 matrix1.set(savedMatrix); matrix1.postTranslate(event.getX() - x_down , event.getY() - y_down); // 平移 matrixCheck = matrixCheck(); matrixCheck = matrixCheck(); if (matrixCheck == false ) { matrix.set(matrix1); invalidate(); } } break ; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mode = NONE; break ; } return true ; } //对图片的矩阵进行检测 private boolean matrixCheck() { float [] f = new float [ 9 ]; matrix1.getValues(f); // 图片4个顶点的坐标 float x1 = f[ 0 ] * 0 + f[ 1 ] * 0 + f[ 2 ]; float y1 = f[ 3 ] * 0 + f[ 4 ] * 0 + f[ 5 ]; float x2 = f[ 0 ] * kenan.getWidth() + f[ 1 ] * 0 + f[ 2 ]; float y2 = f[ 3 ] * kenan.getWidth() + f[ 4 ] * 0 + f[ 5 ]; float x3 = f[ 0 ] * 0 + f[ 1 ] * kenan.getHeight() + f[ 2 ]; float y3 = f[ 3 ] * 0 + f[ 4 ] * kenan.getHeight() + f[ 5 ]; float x4 = f[ 0 ] * kenan.getWidth() + f[ 1 ] * kenan.getHeight() + f[ 2 ]; float y4 = f[ 3 ] * kenan.getWidth() + f[ 4 ] * kenan.getHeight() + f[ 5 ]; // 图片现宽度 double width = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); // 缩放比率判断 if (width < widthScreen / 3 || width > widthScreen * 3 ) { return true ; } // 出界判断 if ((x1 < widthScreen / 3 && x2 < widthScreen / 3 && x3 < widthScreen / 3 && x4 < widthScreen / 3 ) || (x1 > widthScreen * 2 / 3 && x2 > widthScreen * 2 / 3 && x3 > widthScreen * 2 / 3 && x4 > widthScreen * 2 / 3 ) || (y1 < heightScreen / 3 && y2 < heightScreen / 3 && y3 < heightScreen / 3 && y4 < heightScreen / 3 ) || (y1 > heightScreen * 2 / 3 && y2 > heightScreen * 2 / 3 && y3 > heightScreen * 2 / 3 && y4 > heightScreen * 2 / 3 )) { return true ; } return false ; } // 触碰两点间距离 private float spacing(MotionEvent event) { //通过三角函数得到两点间的距离 float x = event.getX( 0 ) - event.getX( 1 ); float y = event.getY( 0 ) - event.getY( 1 ); return FloatMath.sqrt(x * x + y * y); } // 取手势中心点 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 ); } // 取旋转角度 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); } } |
MainActivity
package com.example.yanlei.yl; import android.graphics.Color; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import android.text.Html; import android.text.Html.ImageGetter; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.text.Editable; import android.text.TextWatcher; import android.widget.EditText; import android.widget.Button; import android.app.Activity; import android.content.Intent; import android.view.MotionEvent; import android.widget.TextView; import android.view.Window; import android.view.WindowManager; public class MainActivity extends AppCompatActivity { //定义TextView对象 private TextView Tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //定义自定义View的对象 MyView myview = new MyView(this); //设置当前页面的视图为自定义的myview setContentView(myview); } }
分类:
android
标签:
android 图片的平移
, 缩放和旋转
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
2013-12-01 认识一个人靠缘分;了解一个人靠耐心;征服一个人靠智慧;处好一个人靠包容。人,相互帮扶才感到温暖;事,共同努力才感到简单;路,有伴同行才感到平坦;友,相互牵挂才感到情深。坚持与人为善,不遗余力地成就他人,也将在不知不觉中成就自己。一人亦人,众人为天;谍事在人,成事在天。