【移动开发】Android中图片的多点触控和缩放

简介:

   前几天做项目用到相机拍照,之后能对图片进行缩放,拖拽,在此我将其单独抽取出来,后面用到时直接拿来用就行了!

效果图:

174133817.png

  注:这里不仅能按钮缩放,还能多点触摸缩放和拖拽功能!

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<? xml  version = "1.0"  encoding = "UTF-8" ?>
< FrameLayout  xmlns:android = "http://schemas.android.com/apk/res/android"
     android:id = "@+id/flayout_img_display"
     android:layout_width = "fill_parent"
     android:layout_height = "fill_parent"
     android:orientation = "vertical"  >
     < LinearLayout
         android:id = "@+id/linearLayout_img_display"
         android:layout_width = "fill_parent"
         android:layout_height = "fill_parent"
         android:layout_gravity = "center"
         android:gravity = "center"  >
         < ImageView
             android:id = "@+id/img_display"
             android:layout_width = "fill_parent"
             android:layout_height = "wrap_content"
             android:paddingBottom = "5.0dip"
             android:paddingTop = "5.0dip"
             android:scaleType = "matrix"  />
     </ LinearLayout >
     < RelativeLayout
         android:id = "@+id/relativeLayout1"
         android:layout_width = "fill_parent"
         android:layout_height = "wrap_content"  >
         < Button
             android:id = "@+id/btn_min"
             android:layout_width = "wrap_content"
             android:layout_height = "wrap_content"
             android:layout_alignParentBottom = "true"
             android:layout_alignParentLeft = "true"
             android:enabled = "false"
             android:text = "缩小"  />
         < Button
             android:id = "@+id/btn_out"
             android:layout_width = "wrap_content"
             android:layout_height = "wrap_content"
             android:layout_alignParentBottom = "true"
             android:layout_alignParentRight = "true"
             android:text = "放大"  />
     </ RelativeLayout >
</ FrameLayout >

2.就一个类:

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
import  android.app.Activity;
import  android.content.Intent;
import  android.graphics.Bitmap;
import  android.graphics.BitmapFactory;
import  android.graphics.Matrix;
import  android.graphics.PointF;
import  android.os.Bundle;
import  android.util.FloatMath;
import  android.util.Log;
import  android.view.MotionEvent;
import  android.view.View;
import  android.view.View.OnClickListener;
import  android.view.View.OnTouchListener;
import  android.widget.Button;
import  android.widget.FrameLayout;
import  android.widget.ImageView;
import  android.widget.LinearLayout;
/**
  * 缩放图片界面
  * @author ZHF
  *
  */
public  class  MainActivity  extends  Activity {
     public  static  final  String TAG =  "ImgDisplayActivity" ;
     //控件声明
     private  Button btnZoomin, btnZoomout;
     private  ImageView imgDisPlay;
     private  LinearLayout lLayoutDisplay;
     private  FrameLayout fLayoutDisplay;
                                                                                                            
     private  Bitmap bitmap;
                                                                                                            
     private  int  imgId =  0 ;
     private  double  scale_in =  0.8 ; //缩小比例
     private  double  scale_out =  1.25 ; //放大比例
                                                                                                            
     private  float  scaleWidth =  1 ;
     private  float  scaleHeight =  1 ;
     //模式:0:什么都不干;1:拖拽; 2:缩放
     public  static  final  int  NONE =  0 ;
     public  static  final  int  DRAG =  1 ;
     public  static  final  int  ZOOM =  2 ;
     //声明触发的事件模式
     private  int  mode = NONE;
                                                                                                            
     private  Matrix matrix;    //矩阵
     private  Matrix currMatrix;  //当前矩阵
                                                                                                            
     private  PointF starPoint;
     private  PointF midPoint;
                                                                                                            
     private  float  startDistance;
                                                                                                            
     @Override
     protected  void  onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         //初始化
         fLayoutDisplay = (FrameLayout) findViewById(R.id.flayout_img_display);
         lLayoutDisplay = (LinearLayout) findViewById(R.id.linearLayout_img_display);
         imgDisPlay = (ImageView) findViewById(R.id.img_display);
         btnZoomin = (Button) findViewById(R.id.btn_min);
         btnZoomout = (Button) findViewById(R.id.btn_out);
                                                                                                                
                                                                                                                
         matrix =  new  Matrix();  //保存拖拽变化
         currMatrix =  new  Matrix(); // 当前的
         starPoint =  new  PointF(); //开始点的位置
                                                                                                                
                                                                                                                
         btnZoomin.setOnClickListener( new  OnClickListener() {
             @Override
             public  void  onClick(View v) {
                 zoomIn();
             }
         });
         btnZoomout.setOnClickListener( new  OnClickListener() {
             @Override
             public  void  onClick(View v) {
                 zoomOut(); //放大
             }
         });
                                                                                                                
         imgDisPlay.setImageResource(R.drawable.img);
         //给图片绑定监听器哦
         imgDisPlay.setOnTouchListener( new  ImageViewOnTouchListener());
                                                                                                                
     }
                                                                                                            
     /**放大操作**/
     private  void  zoomOut() {
         reSizeBmp(scale_out);
         btnZoomin.setEnabled( true );
     }
                                                                                                            
     /**缩小操作**/
     private  void  zoomIn() {
         reSizeBmp(scale_in);
     }
                                                                                                            
     /**接收传入的缩放比例实现缩放**/
     private  void  reSizeBmp( double  scale) {
         //缩放比例
         scaleWidth = ( float ) (scaleWidth * scale);
         scaleHeight = ( float ) (scaleHeight * scale);
                                                                                                                
         Matrix matrix =  new  Matrix();
         matrix.postScale(scaleWidth, scaleHeight);  //设计缩放比例
                                                                                                                
         imgDisPlay.setImageMatrix(matrix);
     }
                                                                                                            
     /**计算触摸实现缩放**/
     final  class  ImageViewOnTouchListener  implements  OnTouchListener{
         @Override
         public  boolean  onTouch(View v, MotionEvent event) {
                                                                                                                    
             switch  (event.getAction() & MotionEvent.ACTION_MASK) {
             case  MotionEvent.ACTION_DOWN:   //一只手指按下
                 Log.i(TAG, "一只手指按下" );
                 currMatrix.set(matrix);
                 starPoint.set(event.getX(), event.getY());
                                                                                                                        
                 mode = DRAG;
                 break ;
             case  MotionEvent.ACTION_POINTER_DOWN:  //如果有一只手指按下屏幕,后续又有一个手指按下     // 两只手指按下
                 Log.i(TAG, "又有一只手指按下" );
                                                                                                                        
                 startDistance = distance(event); //记下两点的距离
                 Log.i(TAG, startDistance+ "" );
                                                                                                                        
                 if (startDistance > 5f) {   //两个手指之间的最小距离像素大于5,认为是多点触摸
                     mode = ZOOM;
                     currMatrix.set(matrix);
                                                                                                                            
                     midPoint = getMidPoint(event);  //记下两个点之间的中心点
                                                                                                                            
                 }
                                                                                                                        
                 break ;
                                                                                                                        
             case  MotionEvent.ACTION_MOVE:
                                                                                                                        
                 if (mode == DRAG) {   //拖拽模式
                     Log.i(TAG, "一只手指在拖拽" );
                                                                                                                            
                     //开始--》结束点的距离
                     float  dx = event.getX() - starPoint.x;
                     float  dy = event.getY() - starPoint.y;
                                                                                                                            
                     matrix.set(currMatrix);
                     matrix.postTranslate(dx, dy); //移动到指定点:矩阵移动比例;eg:缩放有缩放比例
                 else  if (mode == ZOOM) {   //缩放模式
                     Log.i(TAG, "正在缩放" );
                                                                                                                            
                     float  distance = distance(event);   //两点之间的距离
                     if (distance > 5f) {
                         matrix.set(currMatrix);
                         float  cale = distance / startDistance;
                         matrix.preScale(cale, cale, midPoint.x, midPoint.y);   //进行比例缩放
                     }
                 }
                 break ;
                                                                                                                        
             case  MotionEvent.ACTION_UP:  //最后一只手指离开屏幕后触发此事件
             case  MotionEvent.ACTION_POINTER_UP:  //一只手指离开屏幕,但还有一只手指在上面会触此事件
                 //什么都没做
                 mode = NONE;
                 break ;
             default :
                 break ;
             }
                                                                                                                    
             imgDisPlay.setImageMatrix(matrix);
                                                                                                                    
             //两只手指的缩放
             return  true ;
         }
     }
                                                                                                            
     /**计算两点之间的距离像素**/
     private  float  distance(MotionEvent e) {
                                                                                                                
         float  eX = e.getX( 1 ) - e.getX( 0 );   //后面的点坐标 - 前面点的坐标
         float  eY = e.getY( 1 ) - e.getY( 0 );
         return  FloatMath.sqrt(eX * eX + eY * eY);
     }
                                                                                                            
     /**计算两点之间的中心点**/
     private  PointF getMidPoint(MotionEvent event) {
                                                                                                                
         float  x = (event.getX( 1 ) - event.getX( 0 )) /  2 ;
         float  y = (event.getY( 1 ) - event.getY( 0 )) /  2 ;
         return  new  PointF(x,y);
     }
}


    ok!主要的算法就在ImageViewOnTouchListener监听器当中,要考虑那三种情况(缩放、拖拽、什么都不干),另外需要注意的就是,单个手指和两个以上手指的情况。


源码下载:http://down.51cto.com/data/876165







     本文转自zhf651555765 51CTO博客,原文链接:http://blog.51cto.com/smallwoniu/1252191,如需转载请自行联系原作者

相关文章
|
4月前
|
XML JSON Java
Android App开发即时通信中通过SocketIO在客户端与服务端间传输文本和图片的讲解及实战(超详细 附源码)
Android App开发即时通信中通过SocketIO在客户端与服务端间传输文本和图片的讲解及实战(超详细 附源码)
72 0
|
25天前
|
Android开发
Android保存图片到相册(适配android 10以下及以上)
Android保存图片到相册(适配android 10以下及以上)
22 1
|
4月前
|
API Android开发
[Android]图片加载库Glide
[Android]图片加载库Glide
55 0
|
4月前
|
Android开发
[Android]制作9-Patch图片
[Android]制作9-Patch图片
42 0
|
4月前
|
XML Java Android开发
Android App接管手势处理TouchEvnet中单点触摸和多点触控的讲解及实战(附源码 超简单实用)
Android App接管手势处理TouchEvnet中单点触摸和多点触控的讲解及实战(附源码 超简单实用)
36 0
|
4月前
|
XML JSON Android开发
Android App开发实战项目之给用户推荐旅游信息图片(附源码 简单易懂)
Android App开发实战项目之给用户推荐旅游信息图片(附源码 简单易懂)
50 0
|
4月前
|
XML 缓存 Java
Android App开发之利用Glide实现图片的三级缓存Cache讲解及实战(附源码 超详细必看 简单易懂)
Android App开发之利用Glide实现图片的三级缓存Cache讲解及实战(附源码 超详细必看 简单易懂)
123 0
|
4月前
|
XML 算法 Java
Android Studio App开发之利用图像解码器ImageDecoder播放GIF动图、Webp、HEIF图片(附源码 简单实用)
Android Studio App开发之利用图像解码器ImageDecoder播放GIF动图、Webp、HEIF图片(附源码 简单实用)
111 0
|
6天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
24 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
28天前
|
Java Android开发
Android 开发获取通知栏权限时会出现两个应用图标
Android 开发获取通知栏权限时会出现两个应用图标
14 0