资讯专栏INFORMATION COLUMN

Android自定义控件1--EventParser

yanbingyun1990 / 458人阅读

摘要:测试效果方向测试角度位移测试速度解析一使用初始化时初始化并为设置监听器在里为设置解析对象不止是,在中也可以用只有有初始化为设置监听器设置解析对象这样所有的这些事件参数就是你的了。

零、前言
自定义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
/**
 * 作者:张风捷特烈
* 时间: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); } }

2.方向枚举:
/**
 * 作者:张风捷特烈
* 时间: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; } }

3.事件监听回调
/**
 * 作者:张风捷特烈
* 时间: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); }

4.事件处理适配器
/**
 * 作者:张风捷特烈
* 时间: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) { } }

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/14894.html

相关文章

  • Android定义控件1--EventParser

    摘要:测试效果方向测试角度位移测试速度解析一使用初始化时初始化并为设置监听器在里为设置解析对象不止是,在中也可以用只有有初始化为设置监听器设置解析对象这样所有的这些事件参数就是你的了。 零、前言 自定义View经常和事件打交道,不过那个event对象用着感觉挺麻烦 打算自己写一个事件的解析类来辅助事件的分析,功能包括: 1.点击监听:回调-->传出落点(类型PointF) 2.抬起监...

    wanglu1209 评论0 收藏0
  • 定义view控件效果实现及实践

    摘要:项目需求讨论自定义实现步骤及封装根据实际项目需求出发。自定义控件之带下载进度的下载按钮最近要用到一个带下载进度的按钮,各种搜索了一波,很抱歉,实在没有发现自己想要的效果,没办法只能自己尝试实现了一个了。 项目需求讨论 - Android 自定义 Dialog 实现步骤及封装 根据实际项目需求出发。因为项目中的对话框要配合整个项目的 UI 风格,所以进行自定义 Dialog 的实现步骤,...

    shiweifu 评论0 收藏0
  • 组合定义控件的步骤详解

    摘要:步骤自定义组合控件的布局自动更新自动更新关闭该控件不支持点击事件,且不能获取焦点创建一个自定义子和控件的类自定义组合控件标题文本控件描述复选框组合自定义控件界面根节点对象把自定义组合控件的文件实例化为对象,并且添加到当前对象中,作 Android 步骤: 1 自定义组合控件的布局settint_view.xml 2 创建一个自...

    zebrayoung 评论0 收藏0
  • 定义控件及效果

    摘要:实现炫酷的登录效果美观,动画效果丰富风格底部选择器支持时间,日期,自定义带来一组风格底部选择器控件,虽然我们不提倡安卓使用风格的控件,但是难免有些产品和美工一味追求风格。 Android 动画效果定值范围选择控件 实现固定值的范围选择, 并添加动态效果, 使用方便 项目需求讨论 - Android 自定义 Dialog 实现步骤及封装 根据实际项目需求出发。因为项目中的对话框要配合整个...

    刘德刚 评论0 收藏0
  • 控件 - 收藏集 - 掘金

    摘要:它也是一款可以帮助你轻松实现侧滑效果的控件掘金一个灵活易用可以帮助开发者实现侧滑效果的开源项目。直接上图站多媒体选择器掘金基于模式的多媒体选择器。 Android 开源库 V - Layout:手把手带你分析 淘宝、天猫都在用的 UI 框架 - Android - 掘金前言 V- Layout 是阿里出品的基础 UI 框架,用于快速实现页面的复杂布局,在手机天猫 Android版 内广...

    sixgo 评论0 收藏0

发表评论

0条评论

yanbingyun1990

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<