当前位置:   article > 正文

【鸿蒙】HarMonyOS的自定义组件一_鸿蒙app开发自定义leida扫描组件

鸿蒙app开发自定义leida扫描组件

当Java UI框架提供的组件无法满足设计需求时,可以创建自定义组件,根据设计需求添加绘制任务,并定义组件的属性及事件响应,完成组件的自定义。

常用接口

表1 Component类相关接口

接口名

作用

setEstimateSizeListener

设置测量组件的侦听器。

onEstimateSize

测量组件的大小以确定宽度和高度。

setEstimatedSize

将测量的宽度和高度设置给组件。

EstimateSpec.getChildSizeWithMode

基于指定的大小和模式为子组件创建度量规范。

EstimateSpec.getSize

从提供的度量规范中提取大小。

EstimateSpec.getMode

获取该组件的显示模式。

addDrawTask

添加绘制任务。

onDraw

通过绘制任务更新组件时调用。

如何实现自定义组件

下面以自定义圆环组件为例,介绍自定义组件的通用配置方法:在屏幕中绘制蓝色圆环,并实现点击变化圆环颜色的功能。

图1 在界面中显示的自定义圆环组件

  1. 创建自定义组件的类,并继承Component或其子类,添加构造方法。

    示例代码如下:

    1. public class CustomComponent extends Component{
    2. public CustomComponent(Context context) {
    3. super(context);
    4. }
    5. }

  2. 实现Component.EstimateSizeListener接口,在onEstimateSize方法中进行组件测量,并通过setEstimatedSize方法将测量的宽度和高度设置给组件。示例代码如下:
    1. public class CustomComponent extends Component implements Component.EstimateSizeListener {
    2. public CustomComponent(Context context) {
    3. super(context);
    4. ...
    5. // 设置测量组件的侦听器
    6. setEstimateSizeListener(this);
    7. }
    8. ...
    9. @Override
    10. public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) {
    11. int width = Component.EstimateSpec.getSize(widthEstimateConfig);
    12. int height = Component.EstimateSpec.getSize(heightEstimateConfig);
    13. setEstimatedSize(
    14. Component.EstimateSpec.getChildSizeWithMode(width, width, Component.EstimateSpec.NOT_EXCEED),
    15. Component.EstimateSpec.getChildSizeWithMode(height, height, Component.EstimateSpec.NOT_EXCEED));
    16. return true;
    17. }
    18. }
    • 注意事项
      1. 自定义组件测量出的大小需通过setEstimatedSize设置给组件,并且必须返回true使测量值生效。
      2. setEstimatedSize方法的入参携带模式信息,可使用Component.EstimateSpec.getChildSizeWithMode方法进行拼接。
    • 测量模式测量组件的宽高需要携带模式信息,不同测量模式下的测量结果也不相同,需要根据实际需求选择适合的测量模式。
      表2 测量模式信息

      模式

      作用

      UNCONSTRAINT

      父组件对子组件没有约束,表示子组件可以任意大小。

      PRECISE

      父组件已确定子组件的大小。

      NOT_EXCEED

      已为子组件确定了最大大小,子组件不能超过指定大小。

  3. 实现Component.DrawTask接口,在onDraw方法中执行绘制任务,该方法提供的画布Canvas,可以精确控制屏幕元素的外观。在执行绘制任务之前,需要定义画笔Paint。

    示例代码如下:

    1. public class CustomComponent extends Component implements Component.DrawTask,Component.EstimateSizeListener {
    2. // 圆环宽度
    3. private static final float CIRCLE_STROKE_WIDTH = 100f;
    4. // 绘制圆环的画笔
    5. private Paint circlePaint;
    6. public CustomComponent(Context context) {
    7. super(context);
    8. // 初始化画笔
    9. initPaint();
    10. // 添加绘制任务
    11. addDrawTask(this);
    12. }
    13. private void initPaint(){
    14. circlePaint = new Paint();
    15. circlePaint.setColor(Color.BLUE);
    16. circlePaint.setStrokeWidth(CIRCLE_STROKE_WIDTH);
    17. circlePaint.setStyle(Paint.Style.STROKE_STYLE);
    18. }
    19. @Override
    20. public void onDraw(Component component, Canvas canvas) {
    21. // 在界面中绘制一个圆心坐标为(500,500),半径为400的圆
    22. canvas.drawCircle(500,500,400,circlePaint);
    23. }
    24. ...
    25. }

  4. 实现Component.TouchEventListener或其他事件的接口,使组件可响应用户输入。示例代码如下:
    1. public class CustomComponent extends Component implements Component.DrawTask, Component.EstimateSizeListener, Component.TouchEventListener {
    2. ...
    3. public CustomComponent(Context context) {
    4. ...
    5. // 设置TouchEvent响应事件
    6. setTouchEventListener(this);
    7. }
    8. ...
    9. @Override
    10. public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
    11. switch (touchEvent.getAction()) {
    12. case TouchEvent.PRIMARY_POINT_DOWN:
    13. circlePaint.setColor(Color.GREEN);
    14. invalidate();
    15. break;
    16. case TouchEvent.PRIMARY_POINT_UP:
    17. circlePaint.setColor(Color.YELLOW);
    18. invalidate();
    19. break;
    20. }
    21. //允许触摸事件触发后进行回调,一定要为true,不然只会监听按下的点击事件,不会触发弹起的事件
    22. return true;
    23. }
    24. }
    • 注意事项
      1. 需要更新UI显示时,可调用invalidate()方法。
      2. 示例中展示TouchEventListener为响应触摸事件,除此之外还可实现ClickedListener响应点击事件、LongClickedListener响应长按事件等。
  5. 在onStart()方法中,将自定义组件添加至UI界面中。
    1. @Override
    2. protected void onStart(Intent intent) {
    3. super.onStart(intent);
    4. DirectionalLayout.LayoutConfig config = new DirectionalLayout.LayoutConfig(
    5. DirectionalLayout.LayoutConfig.MATCH_PARENT, DirectionalLayout.LayoutConfig.MATCH_PARENT);
    6. myLayout.setLayoutConfig(config);
    7. CustomComponent customComponent = new CustomComponent(this);
    8. DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(1080, 1000);
    9. customComponent.setLayoutConfig(layoutConfig);
    10. myLayout.addComponent(customComponent);
    11. super.setUIContent(myLayout);
    12. }

    接下来是绘制矩形,三角形,线条,三角形,点,绘制文字等等效果,代码如下

  1. @Override
  2. public void onDraw(Component component, Canvas canvas) {
  3. //绘制图形
  4. // 在界面中绘制一个圆心坐标为(500,500),半径为400的圆
  5. canvas.drawCircle(200,400,100,paint);
  6. //左上角坐标点为(100,100),右下角坐标点为(200,200),绘制一个正方形
  7. canvas.drawRect(100,100,200,200,paint);
  8. //绘制文字
  9. canvas.drawChars(paint,new char[]{'你','好','鸿','蒙'},100,700);
  10. canvas.drawCharSequence(paint,"加油华为",100,900);
  11. //画线
  12. canvas.drawLine(500,100,700,500,paint);
  13. //画点
  14. canvas.drawPoint(900,900,paint);
  15. //画三角形
  16. canvas.drawLines(new float[]{400,700,600,800,
  17. 600,800,500,600,
  18. 500,600,400,700},paint);
  19. }

其效果如下:绘制的图形效果和通过触摸事件点击之后的效果,手指离开屏幕后恢复颜色

整个自定义组件完整代码如下:

  1. package com.example.hm_phone_java.views;
  2. import ohos.agp.components.Component;
  3. import ohos.agp.render.Canvas;
  4. import ohos.agp.render.Paint;
  5. import ohos.agp.utils.Color;
  6. import ohos.app.Context;
  7. import ohos.multimodalinput.event.TouchEvent;
  8. public class CustomComponent extends Component implements Component.EstimateSizeListener, Component.DrawTask, Component.TouchEventListener {
  9. public CustomComponent(Context context) {
  10. super(context);
  11. //添加组件大小监听器
  12. setEstimateSizeListener(this);
  13. //初始化画笔
  14. initPaint();
  15. // 添加绘制任务
  16. addDrawTask(this);
  17. //添加触摸事件
  18. setTouchEventListener(this);
  19. }
  20. @Override
  21. public boolean onEstimateSize(int width, int height) {
  22. int w=Component.EstimateSpec.getSize(width);
  23. int h=Component.EstimateSpec.getSize(height);
  24. setEstimatedSize(
  25. //NOT_EXCEED 已为子组件确定了最大大小,子组件不能超过指定大小。
  26. //PRECISE 父组件已确定子组件的大小。
  27. //UNCONSTRAINT 父组件对子组件没有约束,表示子组件可以任意大小。
  28. Component.EstimateSpec.getChildSizeWithMode(w,w, EstimateSpec.NOT_EXCEED),
  29. Component.EstimateSpec.getChildSizeWithMode(h,h, EstimateSpec.NOT_EXCEED)
  30. );
  31. return true;
  32. }
  33. // 圆环宽度
  34. private static final float CIRCLE_STROKE_WIDTH = 50f;
  35. // 绘制圆环的画笔
  36. private Paint paint;
  37. public void initPaint(){
  38. //创建画笔
  39. paint=new Paint();
  40. //设置画笔颜色
  41. paint.setColor(Color.BLUE);
  42. //设置线条宽度
  43. paint.setStrokeWidth(CIRCLE_STROKE_WIDTH);
  44. //设置线条样式
  45. //STROKE_STYLE 空心线条
  46. //FILL_STYLE 实心
  47. //FILLANDSTROKE_STYLE实心和边框线条
  48. paint.setStyle(Paint.Style.FILL_STYLE);
  49. //设置绘制文字大小
  50. paint.setTextSize(60);
  51. }
  52. @Override
  53. public void onDraw(Component component, Canvas canvas) {
  54. //绘制图形
  55. // 在界面中绘制一个圆心坐标为(500,500),半径为400的圆
  56. canvas.drawCircle(200,400,100,paint);
  57. //左上角坐标点为(100,100),右下角坐标点为(200,200),绘制一个正方形
  58. canvas.drawRect(100,100,200,200,paint);
  59. //绘制文字
  60. canvas.drawChars(paint,new char[]{'你','好','鸿','蒙'},100,700);
  61. canvas.drawCharSequence(paint,"加油华为",100,900);
  62. //画线
  63. canvas.drawLine(500,100,700,500,paint);
  64. //画点
  65. canvas.drawPoint(900,900,paint);
  66. //画三角形
  67. canvas.drawLines(new float[]{400,700,600,800,
  68. 600,800,500,600,
  69. 500,600,400,700},paint);
  70. }
  71. @Override
  72. public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
  73. switch (touchEvent.getAction()){
  74. case TouchEvent.PRIMARY_POINT_DOWN:
  75. //自定义组件被按下,改变颜色为红色,并重新绘制,刷新图层
  76. paint.setColor(Color.RED);
  77. invalidate();
  78. break;
  79. case TouchEvent.PRIMARY_POINT_UP:
  80. paint.setColor(Color.BLUE);
  81. invalidate();
  82. break;
  83. }
  84. //记得将返回值改为true,表示该监听事件允许回传
  85. return true;
  86. }
  87. }

 界面完整代码如下:

  1. package com.example.hm_phone_java.slice;
  2. import com.example.hm_phone_java.ResourceTable;
  3. import com.example.hm_phone_java.views.CustomComponent;
  4. import ohos.aafwk.ability.AbilitySlice;
  5. import ohos.aafwk.content.Intent;
  6. import ohos.agp.components.DirectionalLayout;
  7. public class OneCustomComponentAbilitySlice extends AbilitySlice {
  8. @Override
  9. protected void onStart(Intent intent) {
  10. super.onStart(intent);
  11. DirectionalLayout myLayout=new DirectionalLayout(this);
  12. DirectionalLayout.LayoutConfig config = new DirectionalLayout.LayoutConfig(
  13. DirectionalLayout.LayoutConfig.MATCH_PARENT, DirectionalLayout.LayoutConfig.MATCH_PARENT);
  14. myLayout.setLayoutConfig(config);
  15. CustomComponent customComponent = new CustomComponent(this);
  16. DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(1080, 1000);
  17. customComponent.setLayoutConfig(layoutConfig);
  18. myLayout.addComponent(customComponent);
  19. super.setUIContent(myLayout);
  20. }
  21. }

并将该界面的类名添加至MainAbility进行引用,接着开启华为模拟器即可看到自定义控件的效果。

初次学习鸿蒙的自定义控件,大家如果掌握的,可以自行绘制图形,比如五边形,六边形,五角星等等

下一篇文章将带着大家使用鸿蒙开发学习自定义组件绘制五星红旗,尽请期待

今天就分享到这里,感谢大家的关注和阅读,因最近工作比较繁忙,没有及时更新文章!!!

下一篇 【鸿蒙】HarMonyOS的自定义组件之五星好评

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/240065
推荐阅读
相关标签
  

闽ICP备14008679号