android绘制触点轨迹的代码

本文实例为大家分享了android绘制触点轨迹的具体代码,供大家参考,具体内容如下

重点函数是onTouchEvent(),所有的触摸事件都会在View的这个函数里面处理

单点触控

单点触控的event是通过event.getAction()获得的,一般最少需要考虑下面这三种情况

MotionEvent.ACTION_DOWN:

  • 手指 初次接触到屏幕 时触发。

MotionEvent.ACTION_MOVE:

  • 手指 在屏幕上滑动 时触发,会多次触发。

MotionEvent.ACTION_UP:

  • 手指 离开屏幕 时触发。

多点触控

多点触控的event是通过event.getActionMasked()获得的,一般最少需要考虑下面这个五种情况,因为有多个点需要处理,所以需要判断event是哪一个触摸点的事件,Android因此导入了比较多的概念,下面通过对关键函数的解析来说明。

注意:方法的说明中添加了我的注释,请留意。另外,每一组函数和这个模块最后都有我写的总结性的文字。

MotionEvent提供了很多看似能直接得到触摸点的方法,但是,这些方法并不是直接拿来能用的,具体的关系如下

getAction()和getActionIndex()以及getActionMasked()

getAction()

 /**
  * Return the kind of action being performed.
  * Consider using {@link #getActionMasked} and {@link #getActionIndex} to retrieve
  * the separate masked action and pointer index.
  * @return The action, such as {@link #ACTION_DOWN} or
  * the combination of {@link #ACTION_POINTER_DOWN} with a shifted pointer index.
  */
 public final int getAction() {
  return nativeGetAction(mNativePtr);//注意返回值表达式
 }

getActionIndex()

 public static final int ACTION_POINTER_INDEX_MASK = 0xff00;
 public static final int ACTION_POINTER_INDEX_SHIFT = 8;
 /**
  * For {@link #ACTION_POINTER_DOWN} or {@link #ACTION_POINTER_UP}
  * as returned by {@link #getActionMasked}, this returns the associated
  * pointer index.
  * The index may be used with {@link #getPointerId(int)},
  * {@link #getX(int)}, {@link #getY(int)}, {@link #getPressure(int)},
  * and {@link #getSize(int)} to get information about the pointer that has
  * gone down or up.
  * @return The index associated with the action.
  */
 public final int getActionIndex() {
 //这个表达式实际就是说取getAction()函数返回值的高8位
  return (nativeGetAction(mNativePtr) & ACTION_POINTER_INDEX_MASK)
    >> ACTION_POINTER_INDEX_SHIFT;
 }

getActionMasked()

 public static final int ACTION_MASK    = 0xff;
 /**
  * Return the masked action being performed, without pointer index information.
  * Use {@link #getActionIndex} to return the index associated with pointer actions.
  * @return The action, such as {@link #ACTION_DOWN} or {@link #ACTION_POINTER_DOWN}.
  */
 public final int getActionMasked() {
 //这个表达式的意思就是说取getAction()函数的低8位
  return nativeGetAction(mNativePtr) & ACTION_MASK;
 }

总结:这就很简单明了了,Acton包含两个部分,高8位表示触摸点的index,低8位表示具体的事件。
注意这里的触摸点的index,指的是Action中的,而不是event中的,这是两个概念。

getPointerId()和findPointerIndex()

getPointerID()

//注意函数的注释第一句的说明,表示,返回的id叫pointer identifier,是和event里面的数据关联的
 /**
  * Return the pointer identifier associated with a particular pointer
  * data index in this event. The identifier tells you the actual pointer
  * number associated with the data, accounting for individual pointers
  * going up and down since the start of the current gesture.
  * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0
  * (the first pointer that is down) to {@link #getPointerCount()}-1.
  */
 public final int getPointerId(int pointerIndex) {
  return nativeGetPointerId(mNativePtr, pointerIndex);
 }

findPointerIndex()

 //注意函数的注释里面第一句,意思是提供一个pointer identifier,返回event中对应数据的index
 //index of data的作用是传给event.getX()等其他的函数来获取坐标等信息
 //所以这个函数的名字改成getPointerDataIndex比较合适
 /**
  * Given a pointer identifier, find the index of its data in the event.
  *
  * @param pointerId The identifier of the pointer to be found.
  * @return Returns either the index of the pointer (for use with
  * {@link #getX(int)} et al.), or -1 if there is no data available for
  * that pointer identifier.
  */
 public final int findPointerIndex(int pointerId) {
  return nativeFindPointerIndex(mNativePtr, pointerId);
 }

总结:这里引入了两个概念,一个是pointer identifier,很好理解,就是指针的id,一个是index of its data.

总结

MotionEvent.getAction返回的是actionIndex和mask的连接体,通过actionIndex可以获取到对应的pointerID,通过pointerID可以获取到对应数据包的ID,然后通过getX()来获取对应的数据信息

基本的使用方法示例

int index = event.getActionIndex();
int id = event.getPointerId(index);
int pointerIndex = event.findPointerIndex(id);
int x=getX(pointerIndex);
int y=getY(pointerIndex);

MotionEvent.ACTION_POINTER_DOWN:

  • 多点触控时按下手指时触发,如果当前只有一个点,则不会触发此事件。

MotionEvent.ACTION_POINTER_DOWN:

  • 多点触控抬起手指时触发,如果当前只有一个点,则不会触发此事件。

MotionEvent.ACTION_DOWN:

  • 第一个手指按下时触发

MotionEvent.ACTION_UP:

  • 最后一个手指离开时触发

MotionEvent.ACTION_MOVE:

1.所有的手指滑动时触发此事件
2.如果有多个点,同时移动,需要在ACTION_MOVE里面添加循环语句。
3.考虑到刷新效率的问题,可以通过event.getHistoricalX()和event.getHistoricalY()来获取存在缓存中的数据,后面的例子中有说明

实例

获取默认屏幕长和宽的代码

WindowManager manager=(WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics=new DisplayMetrics();
Display display=manager.getDefaultDisplay();
display.getMetrics(displayMetrics);
screenW=displayMetrics.widthPixels;
screenH=displayMetrics.heightPixels;

自定义View的代码

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.HashMap;
import java.util.Map;

public class TouchTraceView extends View
{
 Context mContext;
 private Paint line_paint, text_paint, countPaint;
 int screenW, screenH;
 FactoryApplication app;
 private int paintColor = Color.RED;
 Map<Integer, TouchPoint> pointMap;
 float back_x1, back_y1, back_x2, back_y2;

 public TouchTraceView(Context context, AttributeSet attr)
 {
  super(context, attr);
  mContext = context;
  app = ;//作用仅仅是获取默认屏幕的长和宽
  this.screenH = app.screenH;
  this.screenW = app.screenW;
  pointMap = new HashMap<>();
  initPaint();
 }

 private void initPaint()
 {
  line_paint = new Paint();
  line_paint.setAntiAlias(true);
  line_paint.setColor(paintColor);
  text_paint = new Paint();
  text_paint.setAntiAlias(true);
  text_paint.setColor(Color.BLUE);
  text_paint.setTextSize(30);
  countPaint = new Paint();
  countPaint.setAntiAlias(true);
  countPaint.setColor(Color.GREEN);
  countPaint.setTextSize(60);
 }

 @Override
 protected void onDraw(Canvas canvas)
 {
  super.onDraw(canvas);
  int num = pointMap.size();
  if (num == 0)
  {
   clearDraw(canvas);
   return;
  }
  for (Map.Entry<Integer, TouchPoint> entry : pointMap.entrySet())
  {
   TouchPoint point = entry.getValue();
   canvas.drawLine(0, point.y, getWidth(), point.y, line_paint);
   canvas.drawLine(point.x, 0, point.x, getHeight(), line_paint);
   if (num == 1)
   {
    canvas.drawText(" (" + point.x + "," + point.y + ")", screenW / 2, screenH / 2, text_paint);
   } else
   {
    canvas.drawText(String.valueOf(pointMap.size()), screenW / 2, screenH / 2, countPaint);
   }
  }
 }

 @Override
 public boolean onTouchEvent(MotionEvent event)
 {
  int index = event.getActionIndex();
  int id = event.getPointerId(index);
  int pointerIndex = event.findPointerIndex(id);
  int pointerCount = event.getPointerCount();
  int historySize = event.getHistorySize();
  switch (event.getActionMasked())
  {
   case MotionEvent.ACTION_POINTER_DOWN:
    pointMap.put(pointerIndex, new TouchPoint(event.getX(pointerIndex), event.getY(pointerIndex)));
    break;
   case MotionEvent.ACTION_POINTER_UP:
    pointMap.remove(pointerIndex);
    break;
   case MotionEvent.ACTION_MOVE:
    for (int h = 0; h < historySize; h++)
    {
     for (int p = 0; p < pointerCount; p++)
     {
      pointMap.put(p, new TouchPoint(event.getHistoricalX(p, h), event.getHistoricalY(p, h)));
     }
    }
    for (int p = 0; p < pointerCount; p++)
    {
     pointMap.put(p, new TouchPoint(event.getX(p), event.getY(p)));
    }

    break;
   case MotionEvent.ACTION_DOWN:
    pointMap.put(0, new TouchPoint(event.getX(pointerIndex), event.getY(pointerIndex)));
    back_x1 = event.getX();
    back_y1 = event.getY();
    break;
   case MotionEvent.ACTION_UP:
    back_x2 = event.getX();
    back_y2 = event.getY();
    if (Math.abs(back_x1 - back_x2) > screenW / 2 && Math.abs(back_y1 - back_y2) > screenH / 2)
    {
     callOnClick();
    }
    pointMap.clear();
    break;
   default:
    break;
  }
  if (event.getPointerCount() == 0) pointMap.clear();
  invalidate();
  return true;
 }

 class TouchPoint
 {
  public float x = 0;
  public float y = 0;

  TouchPoint(float x, float y)
  {
   this.x = x;
   this.y = y;
  }
 }

 void clearDraw(Canvas canvas)
 {
  Paint paint = new Paint();
  paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
  canvas.drawPaint(paint);
  paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
  canvas.drawColor(Color.WHITE);
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义视图实现手指移动轨迹

    今天看了大神写的关于贝塞尔曲线的博客,就写下了关于手指轨迹的一篇博客, 一.什么是贝塞尔曲线 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线.一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的.贝塞尔曲线是计算机图形学中相当重要的参数曲线,在一些比较成熟的位图软件中也有贝塞尔曲线工具,如PhotoShop等. 二.贝塞尔曲线公式 三.手

  • Android轻松画出触摸轨迹

    本文实例介绍了Android如何画出触摸轨迹的方法,分享给大家供大家参考,具体内容如下 效果图: 实现代码: package com.android.gameview5; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import an

  • Android中SurfaceView和view画出触摸轨迹

    一.引言          想实现一个空白的画板,上面可以画出手滑动的轨迹,就这么一个小需求.一般就来讲就两种实现方式,view或者surfaceview.下面看看两种是如何实现的. 二.实现原理          先简单说一下实现原理:        (1)用一张白色的Bitmap作为画板        (2)用canvas在bitmap上画线        (3)为了画出平滑的曲线,要用canvas的drawPath(Path,Paint)方法.        (4)同时使用贝塞尔曲线来使曲

  • Android 利用三阶贝塞尔曲线绘制运动轨迹的示例

    本篇文章主要介绍了Android 利用三阶贝塞尔曲线绘制运动轨迹的示例,分享给大家,具体如下: 实现点赞效果,自定义起始点以及运动轨迹 效果图: xml布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/rl_root&

  • Android贝塞尔曲线初步学习第三课 Android实现添加至购物车的运动轨迹

    不知上一节高仿QQ未读消息气泡大家还喜欢么,今天继续练习贝赛尔曲线,这一节我们通过贝赛尔曲线和属性动画估值器实现添加至购物车的运动轨迹,效果如下: 1.新建自定义View,重写构造方法,初始化Paint.Path: 2.确定起始点.终止点.控制点坐标,这里我们直接固定: @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh);

  • Android自定义View实现公交成轨迹图

    本文实例为大家分享了Android自定义View实现公交成轨迹图的具体代码,供大家参考,具体内容如下 总体分析下:水平方向recyclewview,item包含定位点,站台位置和站台名称. 下面看实现: 1.继承framelayout,实现构造方法: public class BusStopPlateView extends FrameLayout { ... public BusStopPlateView(@NonNull Context context) { super(context);

  • 解决Android SurfaceView绘制触摸轨迹闪烁问题的方法

    本文分享了解决SurfaceView触摸轨迹闪烁问题的方法,供大家参考,具体内容如下 第一种解决SurfaceView触摸轨迹闪烁问题的方法: 由于SurfaceView使用双缓存机制,两张画布轮流显示到屏幕上.那么,要存储触摸轨迹并避免两张画布内容不一致造成的闪烁问题,完全可以利用保存绘制过程并不断重新绘制的方法解决闪烁,而且这样还顺带解决了多次试验中偶尔出现的因为moveTo()函数不能读取到参数执行默认设置(参数设为上次的触摸点)而出现的断线连接闪烁问题,详细代码如下: package c

  • Android 游戏开发中绘制游戏触摸轨迹的曲线图

    本篇文章主要来讲解怎样绘制游戏触摸轨迹的曲线图. 我们在onTouchEvent方法中,可以获取到触摸屏幕时手指触摸点的x.y坐标,如何用这些点形成一条无规则轨迹并把这条无规则轨迹曲线显示在屏幕上就是本篇文章的主旨内容. Android Path类 Android提供了一个Path类 , 顾名思义这个类可以设置曲线路径轨迹.任何无规则的曲线实际上都是由若干条线段组成,而线段的定义为两点之间最短的一条线.path类就 可以记录这两点之间的轨迹,那么若干个Path 就是我们须要绘制的无规则曲线. 下

  • Android贝塞尔曲线实现手指轨迹

    本文实例为大家分享了Android贝塞尔曲线实现手指轨迹的具体代码,供大家参考,具体内容如下 1.使用贝塞尔曲线前 MyView.java public class MyView extends View { // 实例一个路径对象 private Path mPath = new Path(); public MyView(Context context) { super(context); // TODO Auto-generated constructor stub } public My

  • android绘制触点轨迹的代码

    本文实例为大家分享了android绘制触点轨迹的具体代码,供大家参考,具体内容如下 重点函数是onTouchEvent(),所有的触摸事件都会在View的这个函数里面处理 单点触控 单点触控的event是通过event.getAction()获得的,一般最少需要考虑下面这三种情况 MotionEvent.ACTION_DOWN: 手指 初次接触到屏幕 时触发. MotionEvent.ACTION_MOVE: 手指 在屏幕上滑动 时触发,会多次触发. MotionEvent.ACTION_UP:

  • Android绘制验证码的实例代码

    在前面仿华为加载动画.仿网易音乐听歌识曲-麦克风动画中,我们通过绘图的基础知识完成了简单的绘制.在本例中,我们将绘制常见的验证码. 一.效果图 二.知识点与思路分析 通过上面的效果图观察,我们可以看到里面有绘制的随机线条,随机绘制的验证码. 绘制线条,直线或曲线 绘制文本,生成的验证码文本的绘制 绘制圆点. 三.代码编写 /** * Created by Iflytek_dsw on 2017/7/3. */ public class IdentifyCodeUtil { private sta

  • android绘制几何图形的实例代码

    本文实例为大家分享了android绘制几何图形展示的具体代码,供大家参考,具体内容如下 效果图: 代码(仅绘制类,不可直接运行): public class MyView extends View { public MyView(Context context, AttributeSet set) { super(context, set); } @Override // 重写该方法,进行绘图 protected void onDraw(Canvas canvas) { super.onDraw

  • Android绘制钟表的方法

    本文实例为大家分享了Android绘制钟表的具体代码,供大家参考,具体内容如下 首先要画一个表,我们要先知道步骤如何: 1.仪表盘----外面最大的圆盘 2.刻度线----四个长刻度和剩下的短刻度 3.刻度值----对应的刻度下的数字 4.指针------钟表的三个指针 5.指针动起来 明确思路,下来就是画图了 1.仪表盘,画圆 outCirclePaint = new Paint(); outCirclePaint.setStrokeWidth(2); outCirclePaint.setAn

  • Android基于Mapbox V10 绘制LineGradient轨迹

    目录 前言 普通的 camera Style设定Layer 绘制轨迹LineLayer 前言 当Mapbox升级到V10(我直接到当前的最新V10.3)版本后,就可以就此实现自己想要实现的功能. 官方文档 (docs.mapbox.com/android/map…)上的一些case就不在重复了 UISettings: PreV10 通过MapView 拿到UISettings, 然后控制相关属性,V10 UISettings已经被移除了,不再统一管理,比较分散. 参见相关属性的控制: mMapV

  • Android 绘制多级树形选择列表实例代码

    一.概述 前段时间有个项目的需要在Android端显示一个复选的多层树形控件,主要展示一个公司的组织架构,类似总部下面有各个部门,部门之下是组和员工等.另外需要加上展开与回收部门详情.关闭部分已开展的布局.勾选等功能. 效果图如下: 二.思路分析 毫无疑问,对于这种数据可能达到几千几万行的列表视图,我们需要选择recyclerview等具有回收item功能的控件,因此Item的状态保持放在Model中而不是View中. 由于原始数据是树形结构的,我们需要先将树形结构转换为列表数据,类似根结点 -

  • 使用Python绘制台风轨迹图的示例代码

    参考: 1.Basemap绘制中国地图 2.Basemap生成的图中绘制轨迹 使用CMA热带气旋最佳路径数据集,对我国周边的台风进行绘制 import re import os import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.basemap import Basemap path=r"E:\Computer Science\数学建模\第二次模拟赛题\附件" files= os.listdir(pa

  • Android绘制平移动画的示例代码

    目录 1.具体操作步骤 2.具体实施 创建ImageView 创建ObjectAnimator对象 3.具体实例 activity_main.xml MainActivity.java 1.具体操作步骤 创建ImageView对象 创建ObjectAnimator对象 通过ofFloat方法实现平移 2.具体实施 创建ImageView <ImageView android:id="@+id/car" android:layout_width="wrap_content

  • Android实现绘制折线图APP代码

    目录 一.总体设计 二.具体模块实现 三.效果展示 四.功能展望 总结 一.总体设计 1.寻找规律,公式化的生成坐标系. 2.将生成坐标系的关键参数设置为可自定义,从而可变的可以生成自己想要的坐标系. 3.将需要绘制的点绘制在坐标系中并生成折现图. 二.具体模块实现 1.坐标系的生成: public void chart(){ imageView=(ImageView)findViewById(R.id.image); newb = Bitmap.createBitmap(w, h, Bitma

  • Android利用贝塞尔曲线绘制动画的示例代码

    目录 彩虹系列 弹簧动画 复杂立体感动画 总结 前面我们花了几篇介绍了贝塞尔曲线的原理和绘制贝塞尔曲线,着实让我们见识到了贝塞尔曲线的美.好奇心驱使我想看看贝塞尔曲线动起来会是什么样?本篇就借由动画驱动贝塞尔曲线绘制看看动起来的贝塞尔曲线什么效果. 彩虹系列 通过动画控制绘制的结束点,就可以让贝塞尔曲线动起来.例如下面的动图展示的效果,看起来像搭了一个滑滑梯一样.实际上就是用7条贝塞尔曲线实现的,我们使用了 Animation 对象的值来控制绘制的结束点,从而实现了对应的动画效果. 具体源码如下

随机推荐