Android自定义控件辅助利器之EventParser
时间:2022-06-15
本文章向大家介绍Android自定义控件辅助利器之EventParser,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
零、前言
自定义View经常和事件打交道,不过那个event对象用着感觉挺麻烦 打算自己写一个事件的解析类来辅助事件的分析,功能包括: 1.点击监听:回调-->传出落点(类型PointF) 2.抬起监听:回调-->手指抬起点(类型PointF)、移动方向(类型Orientation,八个) 3.移动监听:回调-->速度(double) y位移(float) x位移(float) 角度(double)、移动方向 4.是否移动、是否按下的判断--------源码比较简单,我注释也很清楚,都贴在文尾,自行cv。
测试效果:
1.方向测试
方向测试.gif
2.角度、位移测试
角度、位移测试.gif
3.速度解析
速度解析.gif
一、使用:
1.view初始化时初始化EventParser并为EventParser设置监听器 2.在onTouchEvent里为mEventParser设置解析对象(不止是view,在Activity中也可以用,只有有event)
public class EventView extends View {
private EventParser mEventParser;
public EventView(Context context) {
this(context, null);
}
public EventView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mEventParser = new EventParser();//初始化EventParser
//为EventParser设置监听器
mEventParser.setOnEventListener(new OnEventListener() {
@Override
public void down(PointF pointF) {
}
@Override
public void up(PointF pointF, Orientation orientation) {
}
@Override
public void move(double v, float dy, float dx, double dir, Orientation orientation) {
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mEventParser.parseEvent(event);//设置解析对象
return true;
}
}
这样所有的这些事件参数就是你的了。 当然也提供了适配器,只想用一个回调方法的,不需要直接实现接口,你可以:
mEventParser.setOnEventListener(new OnEventAdapter(){
@Override
public void move(double v, float dy, float dx, double dir, Orientation orientation) {
}
});
二、代码实现
1.解析器主类:EventParser
/**
* 作者:张风捷特烈<br/>
* 时间:2018/11/6 0006:20:22<br/>
* 邮箱:1981462002@qq.com<br/>
* 说明:事件解析器
*/
public class EventParser {
private OnEventListener onEventListener;
private Orientation mOrientation = Orientation.NO;
private PointF mTagPos;//按下坐标点
//移动时坐标点---在此创建对象,避免在move中创建大量对象
private PointF mMovingPos = new PointF(0, 0);
private float detaY = 0;//下移总量
private float detaX = 0;//右移总量
private boolean isDown = false;//是否按下
private boolean isMove = false;//是否移动
private PointF mDownPos;//记录按下时点
private long lastTimestamp = 0L;//最后一次的时间戳
public void setOnEventListener(OnEventListener onEventListener) {
this.onEventListener = onEventListener;
}
/**
* 添加自己的事件解析
*
* @param event 事件
*/
public void parseEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDown = true;
//按下---为p0赋值
mTagPos = new PointF(event.getX(), event.getY());
mDownPos = mTagPos;
lastTimestamp = System.currentTimeMillis();
if (onEventListener != null) {
onEventListener.down(mTagPos);
}
break;
case MotionEvent.ACTION_MOVE:
//移动的那刻的坐标(移动中,不断更新)
mMovingPos.x = event.getX();
mMovingPos.y = event.getY();
//处理速度
detaX = mMovingPos.x - mDownPos.x;
detaY = mMovingPos.y - mDownPos.y;
//下移单量
float dx = mMovingPos.x - mTagPos.x;
//右移单量
float dy = mMovingPos.y - mTagPos.y;
double ds = Math.sqrt(dx * dx + dy * dy);//偏移位移单量
double dir = deg((float) Math.acos(detaX / ds));//角度
long curTimestamp = System.currentTimeMillis();
long dt = curTimestamp - lastTimestamp;
//由于速度是C*px/ms
double v = ds / dt * 100;
orientationHandler(dir);//处理方向
if (onEventListener != null) {
onEventListener.move(v, detaY, detaX, detaY < 0 ? dir : -dir, mOrientation);
}
if (Math.abs(detaY) > 50 / 3.0) {
isMove = true;
}
mTagPos.x = mMovingPos.x;//更新位置
mTagPos.y = mMovingPos.y;//更新位置----注意这里不能让两个对象相等
lastTimestamp = curTimestamp;//更新时间
break;
case MotionEvent.ACTION_UP:
if (onEventListener != null) {
onEventListener.up(mTagPos, mOrientation);
}
reset();//重置工作
break;
}
}
/**
* 重置工作
*/
private void reset() {
isDown = false;//重置按下状态
isMove = false;//重置移动状态
mDownPos.x = 0;//重置:mDownPos
mDownPos.y = 0;//重置:mDownPos
mOrientation = Orientation.NO;//重置方向
}
/**
* 处理方向
*
* @param dir 方向
*/
private void orientationHandler(double dir) {
if (detaY < 0 && dir > 70 && dir < 110) {
mOrientation = Orientation.TOP;
}
if (detaY > 0 && dir > 70 && dir < 110) {
mOrientation = Orientation.BOTTOM;
}
if (detaX > 0 && dir < 20) {
mOrientation = Orientation.RIGHT;
}
if (detaX < 0 && dir > 160) {
mOrientation = Orientation.LEFT;
}
if (detaY < 0 && dir <= 70 && dir >= 20) {
mOrientation = Orientation.RIGHT_TOP;
}
if (detaY < 0 && dir >= 110 && dir <= 160) {
mOrientation = Orientation.LEFT_TOP;
}
if (detaX > 0 && detaY > 0 && dir >= 20 && dir <= 70) {
mOrientation = Orientation.RIGHT_BOTTOM;
}
if (detaX < 0 && detaY > 0 && dir >= 110 && dir <= 160) {
mOrientation = Orientation.LEFT_BOTTOM;
}
}
public boolean isDown() {
return isDown;
}
public boolean isMove() {
return isMove;
}
/**
* 弧度制化为角度制
*
* @param rad 弧度
* @return 角度
*/
private float deg(float rad) {
return (float) (rad * 180 / Math.PI);
}
}
2.方向枚举:
/**
* 作者:张风捷特烈<br/>
* 时间:2018/11/15 0015:8:14<br/>
* 邮箱:1981462002@qq.com<br/>
* 说明:移动方向枚举
*/
public enum Orientation {
NO("无"),//无
TOP("上"), //上
BOTTOM("下"),//下
LEFT("左"),//左
RIGHT("右"),//右
LEFT_TOP("左上"),// 左上
RIGHT_TOP("右上"), // 右上
LEFT_BOTTOM("左下"),//左下
RIGHT_BOTTOM("右下")//右下
private String or;
Orientation(String or) {
this.or = or;
}
public String value() {
return or;
}
}
3.事件监听回调
/**
* 作者:张风捷特烈<br/>
* 时间:2018/11/15 0015:8:13<br/>
* 邮箱:1981462002@qq.com<br/>
* 说明:事件监听回调
*/
public interface OnEventListener {
/**
* 点击
*
* @param pointF 落点
*/
void down(PointF pointF);
/**
* 抬起
*
* @param pointF 抬起点
* @param orientation 方向
*/
void up(PointF pointF, Orientation orientation);
/**
* 移动
*
* @param v 速度
* @param dy y 位移
* @param dx x位移
* @param dir 角度
* @param orientation 方向
*/
void move(double v, float dy, float dx, double dir, Orientation orientation);
}
4.事件处理适配器
/**
* 作者:张风捷特烈<br/>
* 时间:2018/11/15 0015:8:18<br/>
* 邮箱:1981462002@qq.com<br/>
* 说明:事件处理适配器
*/
public class OnEventAdapter implements OnEventListener {
@Override
public void down(PointF pointF) {
}
@Override
public void up(PointF pointF, Orientation orientation) {
}
@Override
public void move(double v, float dy, float dx, double dir, Orientation orientation) {
}
}
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释