首页 文章详情

自学鸿蒙应用开发(34)- 为自定义UI组件增加触控处理

面向对象思考 | 295 2021-03-17 22:53 0 0 0
UniSMS (合一短信)

动作演示

除了可以描画功能之外,还可以为自定义UI组件增加各种响应,本文以触控事件进行说明。先看演示效果:

构建事件转发类

本文通过构建一个内置TouchEventListener类实现对触控事件的接收和转发。


public class ArcProgressBarContainer extends ComponentContainer implements Component.DrawTask {    // HiLogLabel    private static final HiLogLabel Label = new HiLogLabel(HiLog.LOG_APP, 0x00101, "RoundProgressBarContainer");    private TouchEventListener mTouchEventListener = (component, touchEvent) -> this.onTouchEvent(component, touchEvent);
private int active_bar = 1;
public ArcProgressBarContainer(Context context) { super(context); addDrawTask(this); setTouchEventListener(mTouchEventListener);    }

代码第11行通过setTouchEventListener将内置的TouchEventListener指定为触控事件监听器。


处理触控事件

本例只需要处理触控开始事件:

public boolean onTouchEvent(Component component, TouchEvent touchEvent) {    switch (touchEvent.getAction()) {        case TouchEvent.PRIMARY_POINT_DOWN: {            MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex());            active_bar = hitTest(getComponentPoint(point));            invalidate();            HiLog.warn(Label, "point=%{public}f,%{public}f,hit=%{public}d",                    point.getX(), point.getY(), active_bar);            return true;        }        case TouchEvent.PRIMARY_POINT_UP:            HiLog.debug(Label, "TouchEvent.PRIMARY_POINT_UP");            break;        case TouchEvent.POINT_MOVE: {            HiLog.debug(Label, "TouchEvent.POINT_MOVE");            MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex());            break;        }    }    return false;}

代码第4行获得触控坐标之后,使用如下面代码所示的getComponentPoint将其转换为组件内坐标之后,调用hitTest方法计算选中的进度条。

private MmiPoint getComponentPoint(MmiPoint point){    return new MmiPoint(point.getX() - getLeft(), point.getY() - getTop());}
private int hitTest(MmiPoint point){ int hit = -1; for(int i = 0; i < getChildCount(); ++i){ RectFloat barRect = getProgressRect(i); Point center = barRect.getCenter(); float radius = barRect.getWidth() / 2; float distance = (float) Math.sqrt((point.getX() - center.getPointX()) * (point.getX() - center.getPointX()) + (point.getY() - center.getPointY()) * (point.getY() - center.getPointY())); HiLog.warn(Label, "distance=%{public}f", distance); if(distance <= radius){ hit = i; } else{ break; } } return hit;}

需要注意的是,由于这几个进度条相互重叠,hitTest代码采用由外向内计算距圆心距离的方式寻找选中的进度条。

参考代码

完整代码可以从以下链接下载:

https://github.com/xueweiguo/Harmony/tree/master/CustomizeComponent


作者著作介绍

《实战Python设计模式》是作者去年3月份出版的技术书籍,该书利用Python 的标准GUI 工具包tkinter,通过可执行的示例对23 个设计模式逐个进行说明。这样一方面可以使读者了解真实的软件开发工作中每个设计模式的运用场景和想要解决的问题;另一方面通过对这些问题的解决过程进行说明,让读者明白在编写代码时如何判断使用设计模式的利弊,并合理运用设计模式。

对设计模式感兴趣而且希望随学随用的读者通过本书可以快速跨越从理解到运用的门槛;希望学习Python GUI 编程的读者可以将本书中的示例作为设计和开发的参考;使用Python 语言进行图像分析、数据处理工作的读者可以直接以本书中的示例为基础,迅速构建自己的系统架构。




觉得本文有帮助?请分享给更多人。

关注微信公众号【面向对象思考】轻松学习每一天!

面向对象开发,面向对象思考!



good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter