0917Android基础自定义View的点击事件

TouchEvent

  TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件。这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少,等等。跟touch事件相关的3个方法:

  • public boolean dispatchTouchEvent(MotionEvent ev); //用来分派event
  • public boolean onInterceptTouchEvent(MotionEvent ev); //用来拦截event
  • public boolean onTouchEvent(MotionEvent ev); //用来处理event

每 个 Touch 对象代表一个触点; 每个触点都由其位置,大小,形状,压力大小,和目标 element 描述。 TouchList 对象代表多个触点的一个列表.

属性列表

  • TouchEvent.altKey
    布尔值,指明触摸事件触发时,键盘 alt 键是否被按下。只读属性。
  • TouchEvent.changedTouches
    一个 TouchList 对象,包含了代表所有从上一次触摸事件到此次事件过程中,状态发生了改变的触点的 Touch 对象。只读属性。
  • TouchEvent.ctrlKey
    布尔值,指明触摸事件触发时,键盘 ctrl 键是否被按下。只读属性。
  • TouchEvent.shiftKey
    布尔值,指明触摸事件触发时,键盘 shift 键是否被按下。只读属性。
    TouchEvent.targetTouches
  • TouchEvent.targetTouches
    一个 TouchList 对象,是包含了如下触点的 Touch 对象:触摸起始于当前事件的目标 element 上,并且仍然没有离开触摸平面的触点. 只读属性.
    TouchEvent.touches
  • TouchEvent.touches
    一 个 TouchList 对象,包含了所有当前接触触摸平面的触点的 Touch 对象,无论它们的起始于哪个 element 上,也无论它们状态是否发生了变化。只读属性.
  • TouchEvent.type
    此次触摸事件的类型。 Touch event types 中列出了可能的类型值和详细描述。
  • TouchEvent.target
    此 次触摸事件的目标 element 。这个目标元素对应TouchEvent.changedTouches 中的触点的起始元素(在之后的事件类型中有说明),但是请注意:此次事件中其他的触点的起始元素可能有所不同。以防万一,应使用和每一个单独触点相关联的目标 。
  • TouchEvent.metaKey
    布尔值,指明触摸事件触发时,键盘 meta 键 (Wikipedia - meta Key)是否被按下。只读属性。

触摸事件的类型

为了区别触摸相关的状态改变,存在多种类型的触摸事件。可以通过检查触摸事件的 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上,效果如下。

0917Android基础自定义View的点击事件_第1张图片

  首先将右侧字母栏画出来,新建一个类继承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"
        />

你可能感兴趣的:(0917Android基础自定义View的点击事件)