Skip to content

自定义圆环(Ring)

圆环实现起来很简单,笔者分别通过组合现有控件和通过 Canvas 自绘制的方式向读者介绍如何实现一个自定义组件,通过本节的学习,读者可以掌握向自定义组件传值的方法和回顾 Canvas 的使用。

组合方式

采用组合的方式实现圆环很简单,只需要 2 个 Circle 组件堆叠在一起即可。

创建组件类 Ring

bash

@Component export struct Ring {
  build() {
  }
}
  • @Component:表示 Ring 是一个组件,当使用该修饰符时,必须实现 build() 方法,当组件创建或者后续有状态更新时会调用该方法,我们只需要在 build() 方法内返回布局即可。

  • export:表示当前组件可以导出让外界调用。

实现 Ring 组件的布局

bash

@Component export struct Ring {
  build() {
    Stack({alignContent: Alignment.Center}) {
      Circle()                                // 大圆充满父布局
        .width('100%')
        .height('100%')

      Circle()                                // 小圆居中显示
        .width(83)
        .height(83)
        .fill(Color.White)                    // 填充白色
    }
    .width(90)                                // 宽高相等
    .height(90)                               // 宽高相等
  }
}

预览结果如下所示:

图片

目前通过堆叠的方式实现了 Ring 组件,但是这个圆环不能设置颜色和大小,因此接下来我们需要定义一下圆环的具有的属性。

定义圆环属性 RingAttribute

bash

class RingAttribute {
  radius: number = 45;                                  // 圆环半径,默认45
  width: number  = 5;                                   // 圆环宽度,默认5
  color:Color | number | string | Resource = '#000000'; // 圆环颜色,默认黑色
  solid:Color | number | string | Resource = '#ffffff'; // 填充颜色,默认白色


  /**
   * 对非法参数进行过滤
   */
  public static filter(ringAttribute: RingAttribute): RingAttribute {
    if (null == ringAttribute || undefined == ringAttribute) {
      ringAttribute = new RingAttribute();
    } else {
      var defaultAttribute: RingAttribute = new RingAttribute();
      if (undefined == ringAttribute.color) {
        ringAttribute.color = defaultAttribute.color;
      }
      if (undefined == ringAttribute.width) {
        ringAttribute.width = defaultAttribute.width;
      }
      if (undefined == ringAttribute.radius) {
        ringAttribute.radius = defaultAttribute.radius;
      }
      if (undefined == ringAttribute.solid) {
        ringAttribute.solid = defaultAttribute.solid;
      }
    }
    return ringAttribute;
  }
}

圆环的属性定义后又定义了一个静态方法 filter() ,目的是过滤参数,如果外界没有传递对应的属性就使用默认值,接下来在 Ring 组件里边使用它即可。

使用圆环属性 RingAttribute

bash

@Component export struct Ring {

  public ringAttribute: RingAttribute = null;

  build() {
    Stack({alignContent: Alignment.Center}) {
      Circle()
        .width('100%')
        .height('100%')
        .fill(this.ringAttribute.color)

      Circle()
        .width((this.ringAttribute.radius * 2 - this.ringAttribute.width))
        .height((this.ringAttribute.radius * 2 - this.ringAttribute.width))
        .fill(this.ringAttribute.solid)
    }
    .width(this.ringAttribute.radius * 2)
    .height(this.ringAttribute.radius * 2)
  }

  /**
   * 该方法在build方法执行前先执行,我们可以在这里对参数进行校验
   */
  private aboutToAppear() {
    this.ringAttribute = RingAttribute.filter(this.ringAttribute);
  }
}

aboutToAppear() 方法在 build() 方法执行前会先被执行,因此我们可以在该方法内部对参数进行校验,然后外界就可以使用该组件了。

使用自定义组件 Ring 并传值

bash

import {Ring} from './../common/widgets/ring_widget.ets' // 引入自定义的Ring组件

@Entry @Component struct ComponentTest {

  build() {
    Column() {
      Row({space: 5}) {
        Ring()                 // 显示默认圆环
        Ring({ringAttribute: { // 参数传递
          radius: 40,          // 设置圆环的半径
          width: 8,            // 设置圆环的宽度
          color: Color.Green,  // 设置圆环的颜色
          solid: '#aabbcc'     // 设置圆环的填充色
        }})

        Ring({ringAttribute: { // 参数传递
          radius: 45,          // 设置圆环的半径
          width: 10,           // 设置圆环的宽度
          color: Color.Red,    // 设置圆环的颜色
          solid: Color.Pink    // 设置圆环的填充色
        }})
      }
    }
    .padding(10)
    .width('100%')
    .height('100%')
  }
}

运行结果如下图所示:

图片