摘要:测试效果方向测试角度位移测试速度解析一使用初始化时初始化并为设置监听器在里为设置解析对象不止是,在中也可以用只有有初始化为设置监听器设置解析对象这样所有的这些事件参数就是你的了。
零、前言
自定义View经常和事件打交道,不过那个event对象用着感觉挺麻烦
打算自己写一个事件的解析类来辅助事件的分析,功能包括:
1.点击监听:回调-->传出落点(类型PointF) 2.抬起监听:回调-->手指抬起点(类型PointF)、移动方向(类型Orientation,八个) 3.移动监听:回调-->速度(double) y位移(float) x位移(float) 角度(double)、移动方向 4.是否移动、是否按下的判断--------源码比较简单,我注释也很清楚,都贴在文尾,自行cv。
1.方向测试
2.角度、位移测试
3.速度解析一、使用:
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) { } });二、代码实现
/** * 作者:张风捷特烈
* 时间:2018/11/6 0006:20:22
* 邮箱:1981462002@qq.com
* 说明:事件解析器 */ 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); } }
/** * 作者:张风捷特烈
* 时间:2018/11/15 0015:8:14
* 邮箱:1981462002@qq.com
* 说明:移动方向枚举 */ 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; } }
/** * 作者:张风捷特烈
* 时间:2018/11/15 0015:8:13
* 邮箱:1981462002@qq.com
* 说明:事件监听回调 */ 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); }
/** * 作者:张风捷特烈后记:捷文规范
* 时间:2018/11/15 0015:8:18
* 邮箱:1981462002@qq.com
* 说明:事件处理适配器 */ 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) { } }
项目源码 | 日期 | 备注 |
---|---|---|
V0.1--无 | 2018-11-15 | Android自定义控件辅助利器之EventParser |
1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流,微信:zdl1994328
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/74264.html
阅读 1136·2021-11-10 11:35
阅读 2873·2021-09-24 10:35
阅读 2845·2021-09-22 15:38
阅读 2775·2019-08-30 15:43
阅读 1289·2019-08-29 18:39
阅读 2510·2019-08-29 15:22
阅读 2758·2019-08-28 18:17
阅读 578·2019-08-26 13:37