零、前言

自定义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) {    }});

二、代码实现

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) {    }}

后记:捷文规范

1.本文成长记录及勘误表
项目源码日期备注
V0.1--无2018-11-15Android自定义控件辅助利器之EventParser
2.声明
1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流,微信:zdl1994328
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持