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

简介:

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

效果图:

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

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,如需转载请自行联系原作者

相关文章
|
2月前
|
Java Linux Android开发
移动应用开发与操作系统的交互:深入理解Android和iOS
在数字时代,移动应用成为我们日常生活的一部分。本文将深入探讨移动应用开发的核心概念、移动操作系统的工作原理以及它们如何相互作用。我们将通过实际代码示例,展示如何在Android和iOS平台上创建一个简单的“Hello World”应用,并解释其背后的技术原理。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和知识。
|
20天前
|
IDE 开发工具 Android开发
移动应用开发之旅:探索Android和iOS平台
在这篇文章中,我们将深入探讨移动应用开发的两个主要平台——Android和iOS。我们将了解它们的操作系统、开发环境和工具,并通过代码示例展示如何在这两个平台上创建一个简单的“Hello World”应用。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧,帮助你更好地理解和掌握移动应用开发。
44 17
|
3月前
|
存储 缓存 编解码
Android经典面试题之图片Bitmap怎么做优化
本文介绍了图片相关的内存优化方法,包括分辨率适配、图片压缩与缓存。文中详细讲解了如何根据不同分辨率放置图片资源,避免图片拉伸变形;并通过示例代码展示了使用`BitmapFactory.Options`进行图片压缩的具体步骤。此外,还介绍了Glide等第三方库如何利用LRU算法实现高效图片缓存。
75 20
Android经典面试题之图片Bitmap怎么做优化
|
3月前
|
存储 Java 开发工具
移动应用开发之旅:探索Android操作系统的无限可能
【8月更文挑战第56天】随着智能手机的普及,移动应用已成为我们日常生活中不可或缺的一部分。本文将引导读者了解移动应用开发的基本概念,重点探讨Android操作系统的开发环境搭建、界面设计、功能实现以及与后端服务的交互。通过简单的代码示例和清晰的步骤说明,即便是初学者也能快速入门,开启自己的移动应用开发之旅。
|
3月前
|
设计模式 前端开发 JavaScript
探索移动应用开发:从Android到iOS的跨平台之旅
【9月更文挑战第21天】在这篇文章中,我们将一同揭开移动应用开发的神秘面纱,从Android和iOS这两个主流平台出发,探讨如何利用现代技术栈实现跨平台开发。文章将通过具体的代码示例,带领读者理解不同平台间的差异与联系,以及如何运用React Native框架简化开发流程,实现一次编写,多平台运行的目标。无论你是刚入门的新手还是希望拓展技能的老手,这篇文章都将为你提供宝贵的知识和启示。
74 3
|
2月前
|
开发工具 Android开发 iOS开发
移动应用开发的艺术:探索Android与iOS的操作系统特性
【9月更文挑战第33天】在数字时代的浪潮中,移动应用已成为我们日常生活不可或缺的一部分。本文将深入探讨两个主流移动操作系统——Android和iOS——的独特特性,并分析它们如何影响移动应用的开发过程。我们将通过比较这两个系统的设计哲学、用户界面(UI)设计、开发工具以及市场策略,来揭示开发者如何在这些不同的平台上打造出色的用户体验。无论你是开发者还是对移动技术感兴趣的读者,这篇文章都将为你提供宝贵的见解。
|
4月前
|
机器学习/深度学习 Android开发 iOS开发
探索移动应用开发的未来:Android与iOS的较量
【8月更文挑战第21天】在数字时代的浪潮中,移动应用已成为日常生活不可或缺的一部分。两大主流平台,Android和iOS,各自以其独特的优势和挑战塑造着开发者和用户的世界。本文将深入探讨这两个平台的发展动态、设计理念及其对移动应用开发未来的影响。
|
4月前
|
数据处理 开发工具 数据安全/隐私保护
Android平台RTMP推送|轻量级RTSP服务|GB28181接入之文字、png图片水印的精进之路
本文探讨了Android平台上推流模块中添加文字与PNG水印的技术演进。自2015年起,为了满足应急指挥及安防领域的需求,逐步发展出三代水印技术:第一代为静态文字与图像水印;第二代实现了动态更新水印内容的能力,例如实时位置与时间信息;至第三代,则优化了数据传输效率,直接使用Bitmap对象传递水印数据至JNI层,减少了内存拷贝次数。这些迭代不仅提升了用户体验和技术效率,也体现了开发者追求极致与不断创新的精神。
|
4月前
|
自然语言处理 定位技术 API
Android经典实战之如何获取图片的经纬度以及如何根据经纬度获取对应的地点名称
本文介绍如何在Android中从图片提取地理位置信息并转换为地址。首先利用`ExifInterface`获取图片内的经纬度,然后通过`Geocoder`将经纬度转为地址。注意操作需在子线程进行且考虑多语言支持。
276 4
|
4月前
|
存储 Java 开发工具
移动应用开发之旅:探索Android操作系统的无限可能
【8月更文挑战第31天】 随着智能手机的普及,移动应用已成为我们日常生活中不可或缺的一部分。本文将引导读者了解移动应用开发的基本概念,重点探讨Android操作系统的开发环境搭建、界面设计、功能实现以及与后端服务的交互。通过简单的代码示例和清晰的步骤说明,即便是初学者也能快速入门,开启自己的移动应用开发之旅。