Android中的多点触摸
2016-05-08 22:02
441 查看
我的学习视频地址,一起来学习Android…
http://edu.csdn.net/course/detail/2741/43164?auto_start=1>
代码下载地址
代码一:自定义支持多点触摸的TextView
http://download.csdn.net/detail/zhiyuan0932/9513852
多手指手势操作自定义控件和布局
在只使用单手指操作的时候,这个方法我们一般使用的是event.getAction(),来获取事件类型,但是对于多个手指,我们使用event.getActionMasked()或者event.getAction() & MotionEvent.ACTION_MASK 来获取支持多个手指触摸的事件类型。
MotionEvent.ACTION_POINTER_DOWN 手指按下事件
这个方法可以获取到多个手指按下的状态
MotionEvent.ACTION_POINTER_UP 手指抬起事件
这个方法可以获取到多个手指抬起的状态
MotionEvent.ACTION_MOVE 手指移动事件
event.getPointerCount() 获取手指个数
这个方法是获取当前手指的个数
贴出自定义支持多点触控的TextView代码
第二步:对外提供设置图片的方法
第三步:对图片进行初始化的处理(图片过大需要进行等比例缩放处理),然后将图片绘制到界面上
在进行初始化处理的时候,需要对图片进行缩放和移动,这里将图片小于控件时的偏移量计算原理贴出,方便大家理解
* 第四步:处理onTouch事件
*
第五步 进行图片的缩放处理
下面贴出当图片 大于控件大小时,手指进行缩放时的X轴的偏移量计算原理,来方便大家的理解
http://edu.csdn.net/course/detail/2741/43164?auto_start=1>
代码下载地址
代码一:自定义支持多点触摸的TextView
http://download.csdn.net/detail/zhiyuan0932/9513852
什么是多点触摸
允许计算机用户同时通过多个手指来控制图形界面的一种技术多点触摸的应用场景
对图片、文字、网页进行放大或者缩小多手指手势操作自定义控件和布局
触摸事件的重要方法
event.getActionMasked(); 获取事件类型在只使用单手指操作的时候,这个方法我们一般使用的是event.getAction(),来获取事件类型,但是对于多个手指,我们使用event.getActionMasked()或者event.getAction() & MotionEvent.ACTION_MASK 来获取支持多个手指触摸的事件类型。
MotionEvent.ACTION_POINTER_DOWN 手指按下事件
这个方法可以获取到多个手指按下的状态
MotionEvent.ACTION_POINTER_UP 手指抬起事件
这个方法可以获取到多个手指抬起的状态
MotionEvent.ACTION_MOVE 手指移动事件
event.getPointerCount() 获取手指个数
这个方法是获取当前手指的个数
案例一:通过两指触摸实现字体缩放
在这里直接贴代码,首先贴出布局代码<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.scaletextview.ZoomTextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" android:gravity="center" android:text="@string/hello_world" android:textSize="30sp" /> </RelativeLayout>
贴出自定义支持多点触控的TextView代码
package com.example.scaletextview; import android.content.Context; import android.util.AttributeSet; import android.util.FloatMath; import android.util.Log; import android.view.MotionEvent; import android.widget.TextView; public class ZoomTextView extends TextView { private static final String TAG = "ZoomTextView"; private float textSize; private int mode; private float oldDist; public ZoomTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public ZoomTextView(Context context, AttributeSet attrs) { super(context, attrs); } public ZoomTextView(Context context) { super(context); } /** * 处理TextView的触摸事件 */ @Override public boolean onTouchEvent(MotionEvent event) { //在一开始,计算当前字体的大小 if (textSize == 0) { textSize = this.getTextSize(); } // 获取触摸事件的类型,如果是单点是event.getAction(),当涉及到多点触控时,就使用getActionMasked来获取触摸事件类型 switch (event.getActionMasked()) { case MotionEvent.ACTION_POINTER_DOWN: // 当手指按下的时候,就去获取当前手指的间距 oldDist = spacing(event); break; case MotionEvent.ACTION_MOVE: // 获取当前触摸点的个数 if (event.getPointerCount() >= 2) { // 如果触摸点>=2 获取当前两个手指的距离,然后进行缩放 float newDist = spacing(event); zoom(newDist / oldDist); //重新置位 oldDist = newDist; } break; } return true; } /** * 不断进行缩放 * * @param f */ private void zoom(float f) { textSize *= f; this.setTextSize(px2sp(getContext(), textSize)); } /** * 将px值转换为sp值,保证文字大小不变 * * @param pxValue * @param fontScale * (DisplayMetrics类中属性scaledDensity) * @return */ public static int px2sp(Context context, float pxValue) { float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (pxValue / fontScale + 0.5f); } /** * 计算两个手指的大小 * * @param event * @return */ private float spacing(MotionEvent event) { //获取第一个点的x坐标和第二个点的x坐标 float x = event.getX(0) - event.getX(1); //分别获取y坐标 float y = event.getY(0) - event.getY(1); //使用勾股定理计算两点距离 return FloatMath.sqrt(x * x + y * y); } }
案例二:通过两指触摸实现图片缩放
第一步:写一个自定义控件继承自View,并计算控件宽高public class ScaleImageView extends View //在onMeasure方法中计算出当前控件的宽和高 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = this.getWidth(); height = this.getHeight(); }
第二步:对外提供设置图片的方法
public void setImageResource(int resourceId) { Bitmap mbitmap = BitmapFactory.decodeResource(getResources(), resourceId); this.mBitmap = mbitmap; postInvalidate(); } // 对外提供设置图片的方法 public void setImageBitmap(Bitmap mBitmap) { this.mBitmap = mBitmap; // 当传递过图片来之后,对图片进行初始化操作 postInvalidate(); }
第三步:对图片进行初始化的处理(图片过大需要进行等比例缩放处理),然后将图片绘制到界面上
//进行图片的初始化 public void initBitmap(Canvas canvas) { if (mBitmap != null) { matrix.reset(); int bitmapWidth = mBitmap.getWidth(); int bitmapHeight = mBitmap.getHeight(); if (bitmapWidth > width || bitmapHeight > height) { if (bitmapWidth - width > bitmapHeight - height) { // 当图片宽度大于屏幕宽度时,将图片等比例压缩,使它可以完全显示出来 float ratio = width / (bitmapWidth * 1.0f); matrix.postScale(ratio, ratio); float translateY = (height - (bitmapHeight * ratio)) / 2f; // 在纵坐标方向上进行偏移,以保证图片居中显示 matrix.postTranslate(0, translateY); totalTranslateY = translateY; totalScaleRadio = initScaleRadio = ratio; } else { // 当图片高度大于屏幕高度时,将图片等比例压缩,使它可以完全显示出来 float ratio = height / (bitmapHeight * 1.0f); matrix.postScale(ratio, ratio); float translateX = (width - (bitmapWidth * ratio)) / 2f; // 在横坐标方向上进行偏移,以保证图片居中显示 matrix.postTranslate(translateX, 0); totalTranslateX = translateX; totalScaleRadio = initScaleRadio = ratio; } currentBitmapWidth = bitmapWidth * initScaleRadio; currentBitmapHeight = bitmapHeight * initScaleRadio; } else { // 当图片的宽高都小于屏幕宽高时,直接让图片居中显示 float translateX = (width - mBitmap.getWidth()) / 2f; float translateY = (height - mBitmap.getHeight()) / 2f; matrix.postTranslate(translateX, translateY); totalTranslateX = translateX; totalTranslateY = translateY; totalScaleRadio = initScaleRadio = 1f; currentBitmapWidth = bitmapWidth; currentBitmapHeight = bitmapHeight; } canvas.drawBitmap(mBitmap, matrix, null); } }
在进行初始化处理的时候,需要对图片进行缩放和移动,这里将图片小于控件时的偏移量计算原理贴出,方便大家理解
* 第四步:处理onTouch事件
*
/** * 处理触摸事件 */ @Override public boolean onTouchEvent(MotionEvent event) { // 获取触摸事件的类型,如果是单点是event.getAction(),当涉及到多点触控时,就使用getActionMasked来获取触摸事件类型 switch (event.getActionMasked()) { case MotionEvent.ACTION_POINTER_DOWN: if (event.getPointerCount() >= 2) { // 计算两个手指的距离 oldDist = spacing(event); } break; case MotionEvent.ACTION_MOVE: // 获取当前触摸点的个数 if (event.getPointerCount() >= 2) { centerPoniter(event); // 如果触摸点>=2 获取当前两个手指的距离,然后进行缩放 // 重新置位 float newDist = spacing(event); // 进行缩放 currentState = STATE_ZOOM; // 计算出当前的缩放值 scaleRatio = newDist / oldDist; // 调用onDraw方法,重新绘制界面 postInvalidate(); // 对手指间距离进行重新置位 oldDist = newDist; } break; } return true; }
第五步 进行图片的缩放处理
private void zoom(Canvas canvas) { totalScaleRadio = totalScaleRadio * scaleRatio; //这里是对图片的放大和缩小进行一定的限制 //最大不超过图片的4倍,最小不小于源图片的大小 if (totalScaleRadio >= initScaleRadio * 4) { totalScaleRadio = initScaleRadio * 4; } else if (totalScaleRadio < initScaleRadio) { totalScaleRadio = initScaleRadio; } matrix.reset(); // 将图片按总缩放比例进行缩放 matrix.postScale(totalScaleRadio, totalScaleRadio); float scaledWidth = mBitmap.getWidth() * totalScaleRadio; float scaledHeight = mBitmap.getHeight() * totalScaleRadio; float translateX = 0f; float translateY = 0f; // 如果当前图片宽度小于屏幕宽度,则按屏幕中心的横坐标进行水平缩放。否则按两指的中心点的横坐标进行水平缩放 if (currentBitmapWidth < width) { translateX = (width - currentBitmapWidth) / 2f; } else { //当图片大于控件的大小时,需要去计算出这个偏移量的大小,随后附加图片对这个计算原理做介绍 translateX = mTranslateX * scaleRatio + fingerCenterX * (1 - scaleRatio); // 进行边界检查,保证图片缩放后在水平方向上不会偏移出屏幕 // 当当前图片比屏幕大的时候,要保证不再往右偏,否则就会在右侧移除屏幕 if (translateX > 0) { translateX = 0; // 保证当图片比屏幕大的时候,屏幕宽--左偏的一个大小,不得大于图片的实际大小 } else if (width - translateX > scaledWidth) { translateX = width - scaledWidth; } } // 如果当前图片高度小于屏幕高度,则按屏幕中心的纵坐标进行垂直缩放。否则按两指的中心点的纵坐标进行垂直缩放 if (currentBitmapHeight < height) { translateY = (height - currentBitmapHeight) / 2f; } else { //跟x轴上的偏移量是一个道理 translateY = mTranslateY * scaleRatio + fingerCenterY * (1 - scaleRatio); // 进行边界检查,保证图片缩放后在垂直方向上不会偏移出屏幕 if (translateY > 0) { translateY = 0; } else if (height - translateY > scaledHeight) { translateY = height - scaledHeight; } } // 缩放后对图片进行偏移,以保证缩放后中心点位置不变 matrix.postTranslate(translateX, translateY); mTranslateX = translateX; mTranslateY = translateY; currentBitmapWidth = scaledWidth; currentBitmapHeight = scaledHeight; canvas.drawBitmap(mBitmap, matrix, null); }
下面贴出当图片 大于控件大小时,手指进行缩放时的X轴的偏移量计算原理,来方便大家的理解
计算手指距离和手指中心的方法
/** * 计算两个手指间的距离 * @param event * @return */ private float spacing(MotionEvent event) { // 获取第一个点的x坐标和第二个点的x坐标 float x = event.getX(0) - event.getX(1); // 分别获取y坐标 float y = event.getY(0) - event.getY(1); // 使用勾股定理计算两点距离 return FloatMath.sqrt(x * x + y * y); } /** * 计算手指的中心点 * @param event */ private void centerPoniter(MotionEvent event) { float x0 = event.getX(0); float x1 = event.getX(1); float y0 = event.getY(0); float y1 = event.getY(1); fingerCenterX = (x0 + x1) / 2; fingerCenterY = (y0 + y1) / 2; }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories