摘要:測試效果方向測試角度位移測試速度解析一使用初始化時初始化并為設置監聽器在里為設置解析對象不止是,在中也可以用只有有初始化為設置監聽器設置解析對象這樣所有的這些事件參數就是你的了。
零、前言
自定義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----看到這里,我在此感謝你的喜歡與支持
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74264.html
閱讀 1198·2021-11-10 11:35
閱讀 2925·2021-09-24 10:35
閱讀 2957·2021-09-22 15:38
閱讀 2807·2019-08-30 15:43
閱讀 1338·2019-08-29 18:39
閱讀 2557·2019-08-29 15:22
閱讀 2789·2019-08-28 18:17
閱讀 611·2019-08-26 13:37