Android 中实现图片平移、缩放、旋转同步进行

前言

之前因为项目需求,其中使用到了图片的单击显示取消,图片平移缩放功能,昨天突然想再加上图片的旋转功能,在网上看了很多相关的例子,可是没看到能同时实现我想要的功能的。

需求:
(1)图片平移、缩放、旋转等一系列操作后,图片需要自动居中显示。
(2)图片旋转后选自动水平显示或者垂直显示
(3)图片在放大缩小的同时都能旋转

Demo实现部分效果截图

Demo主要代码

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

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

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;

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

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

}

}

问啊一款面向程序员,共享知识技能的在线交互平台APP

问啊基于共享经济理论,引入一键呼叫模式,一键解决程序员工作中遇到的技
术难题,提高工作效率。

产品形态: 移动客户端
产品链接:http://www.wenaaa.com

时间: 2024-10-10 15:31:50

Android 中实现图片平移、缩放、旋转同步进行的相关文章

WPF/Silverlight中图形的平移,缩放,旋转,倾斜变换演示

原文:WPF/Silverlight中图形的平移,缩放,旋转,倾斜变换演示 为方便描述, 这里仅以正方形来做演示, 其他图形从略. 运行时效果图: XAML代码:// Transform.XAML <Canvas Width="700" Height="700" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  xmlns:x="http://sc

Android实现对图片的缩放、剪切、旋转、存储

Android实现对图片的缩放.剪切.旋转.存储 一.问题描述 在开发中,当我们需要的有一张大图片同时还需要一些小图片时,我们只需要通过代码对此图片进行不同比例的缩放即可,这样大大节约资源,减小了安装包的尺寸 .除缩放外,我们还经常对图片进行其他操作如裁剪.旋转.存储等. 这样我们可以编写对于图片进行处理的通用组件,方便开发.下面就分享一下对图片进行处理的组件BitmapUtil,案例界面: 二.技术点描述 1.通过BitmapFactory取得Bitmap Bitmap bm=BitmapFa

Android中的图片压缩

1.android中计算图片占用堆内存的kB大小跟图片本身的kB大小无关,而是根据图片的尺寸来计算的. 比如一张 480*320大小的图片占用的堆内存大小为: 480*320*4/1024=600kB  之所以要乘以4,是因为在android中使用的ARGB图片,图片一个像素占用四个字节. 2.手机出厂时 堆内存(Heap)是固定的,所以为了不造成OOM,我们就需要生成bitmap时对图片进行压缩处理. 实际使用中我们压缩图片的标准是手机屏幕大小作为参照的,这个主要是因为,即便是图片尺寸跟屏幕尺

Android 中对于图片的内存优化方法

Android 中对于图片的内存优化方法,需要的朋友可以参考一下 1. 对图片本身进行操作 尽量不要使用 setImageBitmap.setImageResource. BitmapFactory.decodeResource 来设置一张大图,因为这些方法在完成 decode 后,最终都是通过 Java 层的 createBitmap 来完成的,需要消耗更多内存.因此,改用先通过 BitmapFactory.decodeStream 方法,创建出一个 bitmap,再将其设为 ImageVie

android 中实现图片倒影效果

1.效果图: 2.核心代码: package com.example.pic_reflection; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.LinearGradient; import android.graphics.Mat

Android中的图片查看器

本案例,使用Eclipse来开发Android2.1版本的图片查看器. 1)首先,打开Eclipse,新建一个Android2.1版本的项目ShowTu,打开res/values中目录下的strings.xml,将其中代码替换成一下代码: 路径:ShowTu/res/valus/string.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="

在Android中实现图片的裁剪

    本实例的功能室将用户选择的图片裁剪后放入ImagView,布局文件是个Button和ImageView.为了图片的正常显示,我们在裁剪后先将裁剪好的图片先存放到SD卡中,这样就能在以后开启应用的时候直接调用了. main_activity.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.androi

【转载】Unity中矩阵的平移、旋转、缩放

By:克森 简介 在这篇文章中,我们将会学到几个概念:平移矩阵.旋转矩阵.缩放矩阵.在学这几个基本概念的同时,我们会用到 Mesh(网格).数学运算.4x4矩阵的一些简单的操作.但由于克森也是新手,文章的严谨性可能不是很高,还请大神们多多指教. 创建项目 首先创建一个Unity工程,克森把他命名为“Matrix of China”(中国的矩阵),基本配置如下图所示: 为了便于查找,让我们在 Assets 目录下新建三个文件夹,分别命名为“Scripts”.“Shader”.“Materials”

Android中9-Patch图片之理解

在android中,不仅可以将扩展名为.png,.jpg,.gif的普通图片作为图片资源,而且可以将扩展名为.9.png的9-Patch图片作为图片资源.扩展名为.png,.jpg,.gif的普通图片较为常见,他们通常是通过绘图软件完成的.而9-Patch图片是通过使用Android SDK中的提供的工具Draw 9-patch生成的.那为什么要使用9-Patch这种图片呢?原因是:与普通图片不同,使用9-Patch图片作为屏幕或按钮的背景时,当屏幕的尺寸或按钮的大小改变时,图片可自动缩放,达到