您的位置:首页 > 移动开发 > Android开发

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.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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息