Android中实现双指缩放的功能
安卓中实现将图片缩放的功能提供了一个很好的类:ScaleGestureDetector,本章就介绍使用canvas和ScaleGestureDetector类实现缩放的功能,如果要想详细了解ScaleGestureDetector请参考博文Android的ScaleGestureDetector缩放类详解
1. 先初始化缩放比和图片居中绘制的坐标点
复制代码
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
26float posX, posY; //图片的坐标 int viewWidth, viewHeight; //屏幕的宽高 float widthScale, heightScale; //宽高缩放比 boolean hasInitViewSize; //是否已经初始化视图 public void initSize() { viewWidth = getWidth(); //得到屏幕宽度 viewHeight = getHeight(); //得到屏幕高度 if (viewWidth < 0 && viewHeight < 0) { return; } hasInitViewSize = true; widthScale = viewWidth / imgWidth; //宽高缩放比=屏幕的宽高/屏幕的宽高 heightScale = viewHeight / imgHeight; scaleFactor = Math.min(widthScale, heightScale); //总缩放比取宽高缩放比中最小的 posX = viewWidth / 2 - imgWidth / 2; //使图片居中绘制 posY = viewHeight / 2 - imgHeight / 2; }
2. 创建两个内部类分别继承SimpleOnScaleGestureListener和SimpleOnGestureListener来动态获取缩放比和坐标
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24class MySimpleOnGestureDetector extends GestureDetector.SimpleOnGestureListener { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { posX -= distanceX; //X轴的坐标=X轴的坐标-在X轴方向的移动距离 posY -= distanceY; //y轴的坐标=y轴的坐标-在y轴方向的移动距离 invalidate(); //刷新view return true; } } class MySimpleScaleOnGestureDetector extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { scaleFactor *= detector.getScaleFactor(); //缩放比=缩放比*动态获取的缩放比 scaleFactor = scaleFactor < 0.75 ? (float) 0.75 : scaleFactor > 3 ? 3 : scaleFactor; //控制缩放倍率在0.75-3之间 invalidate(); //刷新view return true; } }
3. 为了移动图片时不超出屏幕,还得进行控制,原则是:图片较小时任意一条边都不能出了边界,图片较大任意一条边都不能进入边界。宽度和高度分别独立计算。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public void checkBounds() { if (scaleFactor > widthScale) { //宽度方向已经填满 posX = Math.min(posX, (scaleFactor - 1) * (imgWidth / 2)); posX = Math.max(posX, viewWidth - imgWidth - (scaleFactor - 1) * (imgWidth / 2)); } else { posX = Math.max(posX, (scaleFactor - 1) * (imgWidth / 2)); posX = Math.min(posX, viewWidth - imgWidth - (scaleFactor - 1) * (imgWidth / 2)); } if (scaleFactor > heightScale) { //高度方向已经填满 posY = Math.min(posY, (scaleFactor - 1) * (imgHeight / 2)); posY = Math.max(posY, viewHeight - imgHeight - (scaleFactor - 1) * (imgHeight / 2)); } else { posY = Math.max(posY, (scaleFactor - 1) * (imgHeight / 2)); posY = Math.min(posY, viewHeight - imgHeight - (scaleFactor - 1) * (imgHeight / 2)); } }
4. 在类中实现onDraw方法进行绘制缩放
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (bitmap == null) { return; } if (!hasInitViewSize) { initSize(); } canvas.save(); //画布保存 checkBounds(); //检查边界,使图片不能超出屏幕 canvas.scale(scaleFactor, scaleFactor, posX + imgWidth / 2, posY + imgHeight / 2); ///以图片的中心为基点进行缩放 canvas.drawBitmap(bitmap, posX, posY, paint); //绘制图片 canvas.restore(); //画布重绘 }
5. 关键点已经差不多写完了,现在将完整的类写上
复制代码
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
110package com.example.mygesture; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; public class MyScaleView extends View { ScaleGestureDetector scaleGestureDetector; float scaleFactor; float posX, posY; int viewWidth, viewHeight; float widthScale, heightScale; boolean hasInitViewSize; Paint paint = new Paint(); Bitmap bitmap; float imgWidth, imgHeight; GestureDetector gestureDetector; public MyScaleView(Context context, @Nullable AttributeSet attrs) { //注意:得在有两个参数的构造函数中实例化ScaleGestureDetector 和GestureDetector super(context, attrs); init(context); } private void init(Context context) { scaleGestureDetector = new ScaleGestureDetector(context, new MySimpleScaleOnGestureDetector()); gestureDetector = new GestureDetector(context, new MySimpleOnGestureDetector()); } class MySimpleOnGestureDetector extends GestureDetector.SimpleOnGestureListener { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { posX -= distanceX; posY -= distanceY; invalidate(); return true; } } class MySimpleScaleOnGestureDetector extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { scaleFactor *= detector.getScaleFactor(); scaleFactor = scaleFactor < 0.75 ? (float) 0.75 : scaleFactor > 3 ? 3 : scaleFactor; invalidate(); return true; } } public void initSize() { viewWidth = getWidth(); viewHeight = getHeight(); if (viewWidth < 0 && viewHeight < 0) { return; } hasInitViewSize = true; widthScale = viewWidth / imgWidth; heightScale = viewHeight / imgHeight; scaleFactor = Math.min(widthScale, heightScale); posX = viewWidth / 2 - imgWidth / 2; posY = viewHeight / 2 - imgHeight / 2; } public void checkBounds() { //检查边界 if (scaleFactor > widthScale) { posX = Math.min(posX, (scaleFactor - 1) * (imgWidth / 2)); posX = Math.max(posX, viewWidth - imgWidth - (scaleFactor - 1) * (imgWidth / 2)); } else { posX = Math.max(posX, (scaleFactor - 1) * (imgWidth / 2)); posX = Math.min(posX, viewWidth - imgWidth - (scaleFactor - 1) * (imgWidth / 2)); } if (scaleFactor > heightScale) { posY = Math.min(posY, (scaleFactor - 1) * (imgHeight / 2)); posY = Math.max(posY, viewHeight - imgHeight - (scaleFactor - 1) * (imgHeight / 2)); } else { posY = Math.max(posY, (scaleFactor - 1) * (imgHeight / 2)); posY = Math.min(posY, viewHeight - imgHeight - (scaleFactor - 1) * (imgHeight / 2)); } } @Override public boolean onTouchEvent(MotionEvent event) { scaleGestureDetector.onTouchEvent(event); //双指缩放 gestureDetector.onTouchEvent(event); //单指移动 return true; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (bitmap == null) { return; } if (!hasInitViewSize) { initSize(); } canvas.save(); checkBounds(); canvas.scale(scaleFactor, scaleFactor, posX + imgWidth / 2, posY + imgHeight / 2); canvas.drawBitmap(bitmap, posX, posY, paint); canvas.restore(); } public void setImageResouse(int resID) { //设置图片 bitmap = BitmapFactory.decodeResource(getResources(), resID); imgWidth = bitmap.getWidth(); imgHeight = bitmap.getHeight(); initSize(); invalidate(); } }
6. 类已经写好了,现在对其使用,创建一个新的Activity
6.1 构造布局文件
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".text.Main8Activity"> <com.example.mygesture.MyScaleView android:id="@+id/activity_main8_myScaleView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
6.2 对应的类中
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package com.example.mygesture.text; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.example.mygesture.MyScaleView; import com.example.mygesture.R; public class Main8Activity extends AppCompatActivity { MyScaleView myScaleView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main8); myScaleView = findViewById(R.id.activity_main8_myScaleView); myScaleView.setImageResouse(R.drawable.q4); } }
7. 所以使用还是很简单的,因为缩放操作模拟器上不好演示,效果图就省略了。
Tip: 小白,写得不好请见谅。若有不对的地方请留言。
关于手势方面的功能点还可以参考Android中实现自定义手势和识别手势的功能,Android中简单实现页面翻转和自动翻转的功能
最后
以上就是朴素微笑最近收集整理的关于Android中实现双指缩放的功能的全部内容,更多相关Android中实现双指缩放内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复