鸿蒙开发基础

文章目录[隐藏]

认识组件与布局

HarmonyOS提供了Ability和AbilitySlice两个基础类,一个有界面的Ability可以由一个或多个AbilitySlice构成,AbilitySlice主要用于承载单个页面的具体逻辑实现和界面UI,是应用显示、运行和跳转的最小单元。AbilitySlice通过setUIContent为界面设置布局。

组件需要进行组合,并添加到界面的布局中。在Java UI框架中,提供了两种编写布局的方式:

  • 在代码中创建布局:用代码创建Component和ComponentContainer对象,为这些对象设置合适的布局参数和属性值,并将Component添加到ComponentContainer中,从而创建出完整界面。
  • 在XML中声明UI布局:按层级结构来描述Component和ComponentContainer的关系,给组件节点设定合适的布局参数和属性值,代码中可直接加载生成此布局。

这两种方式创建出的布局没有本质差别,在XML中声明布局,在加载后同样可在代码中对该布局进行修改。

组件的分类

组件类别

组件名称

功能描述

布局类

PositionLayout、DirectionalLayout、StackLayout、DependentLayout、TableLayout、AdaptiveBoxLayout

提供了不同布局规范的组件容器,例如以单一方向排列的DirectionalLayout、以相对位置排列的DependentLayout、以确切位置排列的PositionLayout等。

显示类

Text、Image、Clock、TickTimer、ProgressBar

提供了单纯的内容显示,例如用于文本显示的Text,用于图像显示的Image等。

交互类

TextField、Button、Checkbox、RadioButton/RadioContainer、Switch、ToggleButton、Slider、Rating、ScrollView、TabList、ListContainer、PageSlider、PageFlipper、PageSliderIndicator、Picker、TimePicker、DatePicker、SurfaceProvider、ComponentProvider

提供了具体场景下与用户交互响应的功能,例如Button提供了点击响应功能,Slider提供了进度选择功能等。

事件

常见的事件:

  • 单击事件
  • 双击事件
  • 滑动事件
  • 长按事件
  • …….

单击事件

定义实现类

  1. 通过id找到组件。
  2. 给按钮组件设置单击事件。
  3. 写一个类实现ClickedListener接口并重写onClick方法。
  4. 编写onClick方法体。
public class MainAbilitySlice extends AbilitySlice {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        Button button = (Button) this.findComponentById(ResourceTable.Id_button1);
        button.setClickedListener(new MyListener());
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}

class MyListener implements Component.ClickedListener{
    @Override
    public void onClick(Component component) {
        Button button = (Button)component;
        button.setText("被点击了!!");
    }
}

当前类作为实现类

public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        Button button = (Button) this.findComponentById(ResourceTable.Id_button1);
        button.setClickedListener(this);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    public void onClick(Component component) {
        Button button = (Button) component;
        button.setText("被点击了!!");
    }
}

匿名内部类

public class MainAbilitySlice extends AbilitySlice {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        Button button = (Button) this.findComponentById(ResourceTable.Id_button1);
        button.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                Button button = (Button) component;
                button.setText("被点击了!!");
            }
        });
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}

也可用lambda表达式

public class MainAbilitySlice extends AbilitySlice {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        Button button = (Button) this.findComponentById(ResourceTable.Id_button1);
        button.setClickedListener(component -> {
            Button button1 = (Button) component;
            button1.setText("被点击了!!");
        });
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}

弊端:写的代码只能使用一次

方法引用

public class MainAbilitySlice extends AbilitySlice {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        Button button = (Button) this.findComponentById(ResourceTable.Id_button1);
        button.setClickedListener(this::myOnClick);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
    
    public void myOnClick(Component component) {
        Button button = (Button) component;
        button.setText("被点击了!!");
    }
}

以上四种方法,常用的是当前类作为实现类方法引用

双击事件

与单击事件类似,代码实现略

  • 通过id找到组件。
  • 给按钮组件设置双击事件。
  • 本类实现DoubleClickedListener接口重写。
  • 重写onDoubleClick方法体。

长按事件

代码实现略

  • 通过id找到组件。
  • 给按钮组件设置长按事件。
  • 本类实现LongClickedListener接口。
  • 重写onLongClicked方法。

滑动事件

滑动包括三个动作:

  • 按下不松
  • 移动
  • 松开

因此有按下位置,松开位置,代码如下

public class MainAbilitySlice extends AbilitySlice implements Component.TouchEventListener {
    Text text;
    int count = 0;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        text = (Text) findComponentById(ResourceTable.Id_text1);
        DirectionalLayout dl = (DirectionalLayout) findComponentById(ResourceTable.Id_dl);
        dl.setTouchEventListener(this);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    /**
     * @param component  表示滑动的那个组件(布局也是一种组件)
     *                   实际上此时代表的就是那个DirectionalLayout这个布局对象。
     * @param touchEvent 动作对象(按下、滑动、抬起)
     * @return
     */
    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        count++;
        int action = touchEvent.getAction();
        if (action == TouchEvent.PRIMARY_POINT_DOWN) {
            text.setText("按下"+count);
        } else if (action == TouchEvent.POINT_MOVE) {
            text.setText("滑动"+count);
        } else if (action == TouchEvent.PRIMARY_POINT_UP) {
            text.setText("松开"+count);
        }
        return true;
    }
}

通过按下位置,松开位置,可以判断滑动方向。

手机中的坐标轴

一般来说很少用到Z轴,所以我们大部分时间只关注X,Y轴

X坐标不变,Y坐标变大:下滑
X坐标不变,Y坐标变小:上滑
Y坐标不变,X坐标变大:右滑
Y坐标不变,X坐标变小:左滑

/**
 * @param component  表示滑动的那个组件(布局也是一种组件)
 *                   <p>
 *                   实际上此时代表的就是那个DirectionalLayout这个布局对象。
 * @param touchEvent 动作对象(按下、滑动、抬起)
 * @return boolean 布尔
 * 如果为true,表示所有的动作都会触发当前方法并执行对应代码。
 * 如果为false,表示只有第一个动作会触发当前方法并执行对应代码。
 * 后续的动作就不会触发当前方法了。
 * 按下 --- 移动 --- 松开
 */
@Override
public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
    count++;
    //获取当前手指对屏幕进行的操作(按下,滑动,抬起)
    int action = touchEvent.getAction();
    if (action == TouchEvent.PRIMARY_POINT_DOWN) {
        //获取按下时手指的位置(坐标)
        MmiPoint point = touchEvent.getPointerPosition(0);
        startX = point.getX();
        startY = point.getY();
        //text.setText(x + "---" + y);
        text.setText("按下");
    } else if (action == TouchEvent.POINT_MOVE) {
        MmiPoint point = touchEvent.getPointerPosition(0);
        float x = point.getX();
        float y = point.getY();
        text.setText(x + "---" + y);
        text.setText("移动");
    } else if (action == TouchEvent.PRIMARY_POINT_UP) {
        text.setText("松开");
        MmiPoint point = touchEvent.getPointerPosition(0);
        float endX = point.getX();
        float endY = point.getY();
        //text.setText(x + "---" + y);
        //拿着按下时手指的位置跟松开时手指的位置进行比较就可以
        if (endX > startX && Math.abs(endY - startY) < 100) {
            text.setText("右滑");
        } else if (endX < startX && Math.abs(endY - startY) < 100) {
            text.setText("左滑");
        } else if (endY > startY && Math.abs(endX - startX) < 100) {
            text.setText("下滑");
        } else if (endY < startY && Math.abs(endX - startX) < 100) {
            text.setText("上滑");
        }
    }
    return true;
}

onTouchEvent()方法的返回值

是boolean类型:

  • 如果为true,表示所有的动作都会触发当前方法并执行对应代码。
  • 如果为false,表示只有第一个动作会触发当前方法并执行对应代码。后续的动作就不会触发当前方法了。

按下 — 移动 — 松开,这是正常的流程,若返回值为false,则只会触发按下,移动与松开不会触发。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值