TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件。这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少,等等。跟touch事件相关的3个方法:
每 个 Touch 对象代表一个触点; 每个触点都由其位置,大小,形状,压力大小,和目标 element 描述。 TouchList 对象代表多个触点的一个列表.
为了区别触摸相关的状态改变,存在多种类型的触摸事件。可以通过检查触摸事件的 TouchEvent.type 属性来确定当前事件属于哪种类型
注意: 在很多情况下,触摸事件和鼠标事件会同时被触发(目的是让没有对触摸设备优化的代码仍然可以在触摸设备上正常工作)。如果你使用了触摸事件,可以调用 event.preventDefault() 来阻止鼠标事件被触发。
touchstart
当用户在触摸平面上放置了一个触点时触发。事件的目标 element 将是触点位置上的那个目标 element
touchend
当一个触点被用户从触摸平面上移除(当用户将一个手指离开触摸平面)时触发。当触点移出触摸平面的边界时也将触发。例如用户将手指划出屏幕边缘。
事件的目标 element 和这个 touchend 事件对应的 touchstart 事件的目标 element 相同,哪怕 touchend 事件触发时,触点已经移出了该 element 。
已经被从触摸平面上移除的触点,可以在 changedTouches 属性定义的 TouchList 中找到。
touchmove
当用户在触摸平面上移动触点时触发。事件的目标 element 和这个 touchend 事件对应的 touchstart 事件的目标 element 相同,哪怕当 touchend 事件触发时,触点已经移出了该 element 。
当触点的半径、旋转角度以及压力大小发生变化时,也将触发此事件。
注意: 不同浏览器上 touchmove 事件的触发频率并不相同。这个触发频率还和硬件设备的性能有关。因此决不能让程序的运作依赖于某个特定的触发频率
touchenter
当触点进入某个 element 时触发。
注意: 此事件没有冒泡过程。
touchleave
当触点离开某个 element 时触发。
注意: 此事件没有冒泡过程。
touchcancel
当触点由于某些原因被中断时触发。有几种可能的原因如下(具体的原因根据不同的设备和浏览器有所不同):
由于某个事件取消了触摸:例如触摸过程被一个模态的弹出框打断。
触点离开了文档窗口,而进入了浏览器的界面元素、插件或者其他外部内容区域。
当用户产生的触点个数超过了设备支持的个数,从而导致 TouchList 中最早的 Touch 对象被取消。
做出手机通讯录右侧滑动栏的效果如下,点击字母变色,然后移动时字幕也变色,将指针指向的字母显示到TextView上,效果如下。
首先将右侧字母栏画出来,新建一个类继承View,然后设置字体大小,通过循环将字母画出。注意设置字体大小时要在onMeasure中设置。执行时先跑构造器再跑onMeasure和onDraw,构造器跑一次,然后onMeasure跑一到两次(横竖屏切换时需要测量两次),onDraw可能一直跑。所以如果将字体设置放到构造器中, mPaintWord.setTextSize(mHeight / 26f);此时高度长度未测量,为0,字体大小自然也为零,很明显不符合要求。
在构造器中初始化画笔,PaintPress用于点击后的效果画笔
mPaintWord = new Paint();
mPaintPress=new Paint();
mPaintWord.setColor(Color.GRAY);
mPaintWord.setTextAlign(Paint.Align.CENTER);//让字母居中对齐
mPaintPress.setColor(Color.BLACK);
mPaintPress.setTextAlign(Paint.Align.CENTER);//让字母居中对齐中对齐
在onMeasure中设置字体大小
mWith = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(mWith, mHeight);
//设置字体大小,必须放在测量里面,
// 先走构造器再走onMeasure(测量可能测量一次或者两次(横竖屏的时候测量两次))再走onDraw(可能运行多次)
mPaintWord.setTextSize(mHeight / 26f);
mPaintPress.setTextSize(mHeight / 26f);
在onDraw中画出26个字母,加条件语句判断字母是否需要变色
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < array.length; i++) {
if(index==i) {
// 设置每个字母的显示位置,宽度去mWith-"m"的宽度是因为m最宽
canvas.drawText(array[i], mWith - mPaintWord.measureText("m"), mHeight / 26 * (i + 1), mPaintPress);
}else {
canvas.drawText(array[i], mWith - mPaintWord.measureText("m"), mHeight / 26 * (i + 1), mPaintWord);
}
}
}
String数组array在一开始就初始化
private String[] array = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o"
, "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
给字母加“动作”
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_DOWN:
// 设置字母按下去的点击事件
x = event.getX();
y = event.getY();
if (x > mWith - mPaintWord.measureText("m") * 2) {
index = (int) (y / (mHeight / 26));
// 防止溢出
if (index >= 26) {
index = 25;
}
Log.d("onTouch", "点击到的按钮是:" + array[index]);
invalidate();
if(onSelectItemListener!=null) {
onSelectItemListener.onSelectItem(index, array[index]);
}
return true;//处理完成
}
break;
case MotionEvent.ACTION_UP:
index = -1;
invalidate();
return true;
default:
break;
}
return super.onTouchEvent(event);
}
在View中写字母的监听事件(监听者模式)
private OnSelectItemListener onSelectItemListener;
public void setOnSelectItemListener(OnSelectItemListener onSelectItemListener) {
this.onSelectItemListener = onSelectItemListener;
}
// 自定义一个接口
public interface OnSelectItemListener{
public void onSelectItem(int index,String indexString);
}
在字母的点击事件中(onTouchEvent)中给重写的方法传递参数
invalidate();
if(onSelectItemListener!=null) {
onSelectItemListener.onSelectItem(index, array[index]);
}
在活动中设置点击事件,获取传递的参数,并设置UI
mSlider= (MyTouchEventView) findViewById(R.id.my_slider);
mTextView= (TextView) findViewById(R.id.textview);
mSlider.setOnSelectItemListener(new MyTouchEventView.OnSelectItemListener() {
@Override
public void onSelectItem(int index,String indexString) {
mTextView.setText(indexString);
}
});
全部代码
//View中
package com.example.laowang.android0916canvas_.weight;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by Administrator on 2015/9/17.
*/
public class MyTouchEventView extends View {
private int mWith;
private int mHeight;
private Paint mPaintWord;
private Paint mPaintPress;
private float x;
private float y;
private int index=-1;//默认为0,这样的话"a"就变色了
private String[] array = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o"
, "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
private OnSelectItemListener onSelectItemListener;
public void setOnSelectItemListener(OnSelectItemListener onSelectItemListener) {
this.onSelectItemListener = onSelectItemListener;
}
// 自定义一个接口
public interface OnSelectItemListener{
public void onSelectItem(int index,String indexString);
}
public MyTouchEventView(Context context) {
super(context);
}
public MyTouchEventView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintWord = new Paint();
mPaintPress=new Paint();
mPaintWord.setColor(Color.GRAY);
mPaintWord.setTextAlign(Paint.Align.CENTER);//让字母居中对齐
mPaintPress.setColor(Color.BLACK);
mPaintPress.setTextAlign(Paint.Align.CENTER);//让字母居中对齐
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWith = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(mWith, mHeight);
//设置字体大小,必须放在测量里面,
// 先走构造器再走onMeasure(测量可能测量一次或者两次(横竖屏的时候测量两次))再走onDraw(可能运行多次)
mPaintWord.setTextSize(mHeight / 26f);
mPaintPress.setTextSize(mHeight / 26f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < array.length; i++) {
if(index==i) {
// 设置每个字母的显示位置,宽度去mWith-"m"的宽度是因为m最宽
canvas.drawText(array[i], mWith - mPaintWord.measureText("m"), mHeight / 26 * (i + 1), mPaintPress);
}else {
canvas.drawText(array[i], mWith - mPaintWord.measureText("m"), mHeight / 26 * (i + 1), mPaintWord);
}
}
}
// 设置字母的点击事件
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_DOWN:
// 设置字母按下去的点击事件
x = event.getX();
y = event.getY();
if (x > mWith - mPaintWord.measureText("m") * 2) {
index = (int) (y / (mHeight / 26));
Log.d("onTouch", "点击到的按钮是:" + array[index]);
invalidate();
if(onSelectItemListener!=null) {
onSelectItemListener.onSelectItem(index, array[index]);
}
return true;//处理完成
}
break;
case MotionEvent.ACTION_UP:
index = -1;
invalidate();
return true;
default:
break;
}
return super.onTouchEvent(event);
}
}
//活动中
public class MainActivity extends Activity implements View.OnClickListener{
private TextView mTextView;
private MyTouchEventView mSlider;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSlider= (MyTouchEventView) findViewById(R.id.my_slider);
mTextView= (TextView) findViewById(R.id.textview);
mSlider.setOnSelectItemListener(new MyTouchEventView.OnSelectItemListener() {
@Override
public void onSelectItem(int index,String indexString) {
mTextView.setText(indexString);
}
});
}
//布局
"http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">"@+id/my_slider"
android:layout_width="match_parent"
android:layout_height="match_parent" />
"@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="200dp"
/>