基于Android 实现图片平移、缩放、旋转同时进行
程序员文章站
2023-12-05 15:17:58
前言
之前因为项目需求,其中使用到了图片的单击显示取消,图片平移缩放功能,昨天突然想再加上图片的旋转功能,在网上看了很多相关的例子,可是没看到能同时实现我想要的功能的。...
前言
之前因为项目需求,其中使用到了图片的单击显示取消,图片平移缩放功能,昨天突然想再加上图片的旋转功能,在网上看了很多相关的例子,可是没看到能同时实现我想要的功能的。
需求:
(1)图片平移、缩放、旋转等一系列操作后,图片需要自动居中显示。
(2)图片旋转后选自动水平显示或者垂直显示
(3)图片在放大缩小的同时都能旋转
demo实现部分效果截图
demo主要代码
java
mainactivity.java package com.practice.noyet.rotatezoomimageview; import android.app.activity; import android.graphics.bitmap; import android.graphics.bitmapfactory; import android.graphics.matrix; import android.graphics.pointf; import android.graphics.rectf; import android.os.asynctask; import android.os.bundle; import android.util.displaymetrics; import android.view.motionevent; import android.view.view; import android.widget.imageview; import com.ypy.eventbus.eventbus; import java.io.file; import java.math.bigdecimal; /** * package: com.practice.noyet.rotatezoomimageview * created by noyet on 2015/11/11. */ public class mainactivity extends activity implements view.ontouchlistener { private imageview mimageview; private pointf point0 = new pointf(); private pointf pointm = new pointf(); private final int none = 0; /** * 平移 */ private final int drag = 1; /** * 旋转、缩放 */ private final int zoom = 2; /** * 设定事件模式 */ private int mode = none; /** * 图片缩放矩阵 */ private matrix matrix = new matrix(); /** * 保存触摸前的图片缩放矩阵 */ private matrix savedmatrix = new matrix(); /** * 保存触点移动过程中的图片缩放矩阵 */ private matrix matrix1 = new matrix(); /** * 屏幕高度 */ private int displayheight; /** * 屏幕宽度 */ private int displaywidth; /** * 最小缩放比例 */ protected float minscale = 1f; /** * 最大缩放比例 */ protected float maxscale = 3f; /** * 当前缩放比例 */ protected float currentscale = 1f; /** * 多点触摸2个触摸点间的起始距离 */ private float olddist; /** * 多点触摸时图片的起始角度 */ private float oldrotation = 0; /** * 旋转角度 */ protected float rotation = 0; /** * 图片初始宽度 */ private int imgwidth; /** * 图片初始高度 */ private int imgheight; /** * 设置单点触摸退出图片显示时,单点触摸的灵敏度(可针对不同手机单独设置) */ protected final int move_max = 2; /** * 单点触摸时手指触发的‘motionevent.action_move'次数 */ private int fingernummove = 0; private bitmap bm; /** * 保存matrix缩放比例 */ private float matrixscale= 1; /*private string imagepath;*/ /** * 显示被存入缓存中的网络图片 * * @param event 观察者事件 */ public void oneventmainthread(customeventbus event) { if (event == null) { return; } if (event.type == customeventbus.eventtype.show_picture) { bm = (bitmap) event.obj; showimage(); } } @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); initdata(); } public void initdata() { // todo auto-generated method stub bm = bitmapfactory.decoderesource(getresources(), r.drawable.alipay); displaymetrics dm = getresources().getdisplaymetrics(); displaywidth = dm.widthpixels; displayheight = dm.heightpixels; mimageview = (imageview) findviewbyid(r.id.image_view); mimageview.setontouchlistener(this); showimage(); //显示网络图片时使用 /*file file = mainapplication.getinstance().getimagecache() .getdiskcache().get(图片路径); if (!file.exists()) { toast.maketext(this, "图片路径错误", toast.length_short).show(); } else { new mytask().execute(file); }*/ } @override public boolean ontouch(view view, motionevent event) { imageview imageview = (imageview) view; switch (event.getaction() & motionevent.action_mask) { case motionevent.action_down: savedmatrix.set(matrix); point0.set(event.getx(), event.gety()); mode = drag; system.out.println("motionevent--action_down"); break; case motionevent.action_pointer_down: olddist = spacing(event); oldrotation = rotation(event); savedmatrix.set(matrix); setmidpoint(pointm, event); mode = zoom; system.out.println("motionevent--action_pointer_down---" + oldrotation); break; case motionevent.action_up: if (mode == drag & (fingernummove this.finish(); } checkview(); centerandrotate(); imageview.setimagematrix(matrix); system.out.println("motionevent--action_up"); fingernummove = 0; break; case motionevent.action_pointer_up: mode = none; system.out.println("motionevent--action_pointer_up"); break; case motionevent.action_move: operatemove(event); imageview.setimagematrix(matrix1); fingernummove++; system.out.println("motionevent--action_move"); break; } return true; } @override protected void ondestroy() { // todo auto-generated method stub super.ondestroy(); if (bm != null & !bm.isrecycled()) { bm.recycle(); // 回收图片所占的内存 system.gc(); // 提醒系统及时回收 } } /** * 显示图片 */ private void showimage() { imgwidth = bm.getwidth(); imgheight = bm.getheight(); mimageview.setimagebitmap(bm); matrix.setscale(1, 1); centerandrotate(); mimageview.setimagematrix(matrix); } /** * 触点移动时的操作 * * @param event 触摸事件 */ private void operatemove(motionevent event) { matrix1.set(savedmatrix); switch (mode) { case drag: matrix1.posttranslate(event.getx() - point0.x, event.gety() - point0.y); break; case zoom: rotation = rotation(event) - oldrotation; float newdist = spacing(event); float scale = newdist / olddist; currentscale = (scale > 3.5f) ? 3.5f : scale; system.out.println("缩放倍数---" + currentscale); system.out.println("旋转角度---" + rotation); /** 縮放 */ matrix1.postscale(currentscale, currentscale, pointm.x, pointm.y); /** 旋轉 */ matrix1.postrotate(rotation, displaywidth / 2, displayheight / 2); break; } } /** * 两个触点的距离 * * @param event 触摸事件 * @return float */ private float spacing(motionevent event) { float x = event.getx(0) - event.getx(1); float y = event.gety(0) - event.gety(1); return (float) math.sqrt(x * x + y * y); } /** * 获取旋转角度 */ 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); } /** * 两个触点的中间坐标 * * @param pointm 中间坐标 * @param event 触摸事件 */ private void setmidpoint(pointf pointm, motionevent event) { float x = event.getx(0) + event.gety(1); float y = event.gety(0) + event.gety(1); pointm.set(x / 2, y / 2); } /** * 检查约束条件(缩放倍数) */ private void checkview() { if (currentscale > 1) { if (currentscale * matrixscale > maxscale) { matrix.postscale(maxscale / matrixscale, maxscale / matrixscale, pointm.x, pointm.y); matrixscale = maxscale; } else { matrix.postscale(currentscale, currentscale, pointm.x, pointm.y); matrixscale *= currentscale; } } else { if (currentscale * matrixscale else { matrix.postscale(currentscale, currentscale, pointm.x, pointm.y); matrixscale *= currentscale; } } } /** * 图片居中显示、判断旋转角度 小于(90 * x + 45)度图片旋转(90 * x)度 大于则旋转(90 * (x+1)) */ private void centerandrotate() { rectf rect = new rectf(0, 0, imgwidth, imgheight); matrix.maprect(rect); float width = rect.width(); float height = rect.height(); float dx = 0; float dy = 0; if (width 2 - width / 2 - rect.left; } else if (rect.left > 0) { dx = -rect.left; } else if (rect.right if (height 2 - height / 2 - rect.top; } else if (rect.top > 0) { dy = -rect.top; } else if (rect.bottom if (rotation != 0) { int rotationnum = (int) (rotation / 90); float rotationavai = new bigdecimal(rotation % 90).setscale(1, bigdecimal.round_half_up).floatvalue(); float realrotation = 0; if (rotation > 0) { realrotation = rotationavai > 45 ? (rotationnum + 1) * 90 : rotationnum * 90; } else if (rotation 0) { realrotation = rotationavai 45 ? (rotationnum - 1) * 90 : rotationnum * 90; } system.out.println("realrotation: " + realrotation); matrix.postrotate(realrotation, displaywidth / 2, displayheight / 2); rotation = 0; } } /** * 显示网络图片时使用 */ private class mytask extends asynctaskfile, file, bitmap> { bitmap bitmap; string path; int scale = 1; long size; @override protected bitmap doinbackground(file... params) { // todo auto-generated method stub try { size = params[0].length(); path = params[0].getabsolutepath(); bitmapfactory.options options = new bitmapfactory.options(); options.injustdecodebounds = true; bitmapfactory.decodefile(path, options); scale = calculateinsamplesize(options, displaywidth, displayheight); options.injustdecodebounds = false; options.insamplesize = scale; bitmap = bitmapfactory.decodefile(path, options); } catch (exception e) { // todo auto-generated catch block e.printstacktrace(); } return bitmap; } @override protected void onpostexecute(bitmap result) { // todo auto-generated method stub eventbus.getdefault().post( new customeventbus(customeventbus.eventtype.show_picture, result)); } /** * 获取图片缩放比例 * * @param paramoptions options * @param paramint1 宽 * @param paramint2 高 * @return int */ private int calculateinsamplesize(bitmapfactory.options paramoptions, int paramint1, int paramint2) { int i = paramoptions.outheight; int j = paramoptions.outwidth; int k = 1; if ((i > paramint2) || (j > paramint1)) { int m = math.round(i / paramint2); int n = math.round(j / paramint1); k = m return k; } } } customeventbus.java package com.practice.noyet.rotatezoomimageview; /** * package: com.practice.noyet.rotatezoomimageview * created by noyet on 2015/11/11. */ public class customeventbus { public eventtype type; public object obj; public customeventbus(eventtype type, object obj) { this.type = type; this.obj = obj; } enum eventtype { show_picture } }
上一篇: Python爬虫实战之12306抢票开源
推荐阅读
-
基于Android 实现图片平移、缩放、旋转同时进行
-
Android 图片缩放与旋转的实现详解
-
Android UI之ImageView实现图片旋转和缩放
-
基于JQuery实现的图片自动进行缩放和裁剪处理
-
Android 图片缩放与旋转的实现详解
-
Android UI之ImageView实现图片旋转和缩放
-
Android自定义ImageView实现图片缩放滑动,双击放大缩小,多点触控旋转,圆角矩形,圆形和仿刮刮卡效果
-
Android动画开发之淡入淡出、缩放、旋转、平移、组合动画效果代码实现
-
基于JQuery实现的图片自动进行缩放和裁剪处理_jquery
-
基于JQuery实现的图片自动进行缩放和裁剪处理