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

2021-04-02 11:14:34 浏览数 (1)

动作演示

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

构建事件转发类

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

代码语言:javascript复制
代码语言:javascript复制
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指定为触控事件监听器。

处理触控事件

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

代码语言:javascript复制
代码语言:javascript复制
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方法计算选中的进度条。

代码语言:javascript复制
代码语言:javascript复制
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

0 人点赞