鴻蒙自定義單選Radio組件

2024年2月6日 21点热度 0人点赞

Radio是單選框組件,通常用於提供相應的用戶交互選擇項,同一組的Radio中隻有一個可以被選中。

ArkUI創建一個單選框,其中value是單選框的名稱,group是單選框的所屬群組名稱。checked屬性可以設置單選框的狀態,狀態分別為false和true時,設置為true時表示單選框被選中。Radio僅支持選中和未選中兩種樣式,不支持自定義顏色和形狀。

Radio({ value: 'Radio1', group: 'radioGroup' }).checked(false)

Radio({ value: 'Radio2', group: 'radioGroup' }).checked(true)

當使用的時,發現不是很友好,沒有對應的文本,而且點擊事件不方便選中單選框。

如果在我們常用表單中,需要用到單選組件復用的情況,使用起來相當不方便。所以封裝了一個單選Radio組件。

import {DynamicObject} from './type'
/**
 * 自定義顏色
 */
@Component
export default  struct DiygwRadio{
  //綁定的值
  @Link @Watch('onValue') value:string;
  // 保存所有單選框的名稱
  @State list: DynamicObject[] = [];
  // 隱藏值
  @State valueField: string = 'value';
  // 顯示值
  @State labelField: string = 'label';
  // 選中/未選中狀態下的圖標
  @State checkedValues: Resource[] = [];
  //選中圖標
  @State checkedImg: Resource = $r('app.media.radioon');
  //未選中圖標
  @State noCheckedImg: Resource = $r('app.media.radio');
  //未選中圖標
  @State labelImg: Resource = $r('app.media.user');
  //是否文本圖片
  @State isLabelImg: boolean = false;
  @State labelImgWidth: number = 20;
  @State labelImgHeight: number = 20;
  //標題文本
  @State label:string = '單選';
  //水平狀態時,文本占大小
  @State labelWidth:number = 80;
  //是否標題文本換行
  @State isWrapLabel:boolean = false;
  //是否標題文本
  @State isLabel:boolean = true;
  //文本字體大小
  @State textSize:number = 14;
  //選中圖版本大小
  @State imgSize:number = 28;
  //每個占比
  @State itemWidth:string = '33%';
  //每行個數
  @State col:number = 3;
  //組件內邊距
  @State formPadding:number = 5;
  //初始化選中
  initCheck(){
    for (let i = 0; i < this.list.length; i  ) {
      if(this.list[i][this.valueField] == this.value) {
        this.checkedValues[i] = this.checkedImg;
      }else{
        this.checkedValues[i] = this.noCheckedImg;
      }
    }
  }
  //監聽選中
  onValue() {
     this.initCheck()
  }
  onChecked(index: number){
    //點擊文本選中當前單選框
    for (let i = 0; i < this.list.length; i  ) {
      this.checkedValues[i] = this.noCheckedImg;
    }
    this.checkedValues[index] = this.checkedImg;
    this.value = this.list[index][this.valueField];
  }
  build() {
    Flex({
      alignItems:this.isWrapLabel?ItemAlign.Start:ItemAlign.Center,
      direction:this.isWrapLabel?FlexDirection.Column:FlexDirection.Row,
      justifyContent:FlexAlign.Start
    }){
      if(this.isLabel){
        Row(){
          if(this.isLabelImg){
            Image(this.labelImg)
              .width(this.labelImgWidth)
              .height(this.labelImgHeight)
              .margin({ left:3 })
          }
          Text(this.label).width(this.isWrapLabel?'100%':this.labelWidth).fontSize(this.textSize).margin({
            bottom:this.isWrapLabel?10:0
          }).textAlign(TextAlign.Start);
        }
      }
      Flex({
        wrap:FlexWrap.Wrap
      }){
        ForEach(this.list, (item: any,index: number) => {
            Row(){
              Image(this.checkedValues[index])
                .borderRadius('50%')
                .size({width: this.imgSize , height: this.imgSize}).margin({
                top:1,
                bottom:1
              })
              Text(item[this.labelField])
                .fontSize(this.textSize)
                .margin({left: 10})
            }.onClick(()=>{
              this.onChecked(index)
            }).width(this.itemWidth)
        })
      }.width('100%')
    }.height(Math.ceil(this.list.length/this.col)*38 (this.isWrapLabel?18:0)).padding(this.formPadding)
    .onAppear(() => {
      let widths=['100%','50%','33%','25%']
      let col = widths.indexOf(this.itemWidth)   1
      this.col = col
      this.initCheck()
    })
  }
}

組件使用代碼

 DiygwRadio({
              isWrapLabel:true,
              itemWidth:'50%',
              value: $radio,
              list: [{
                value: 'radio1',
                label: '單選1'
              }, {
                value: 'radio2',
                label: '單選2'
              }, {
                value: 'radio3',
                label: '單選3'
              }, {
                value: 'radio21',
                label: '單選2'
              }, {
                value: 'radio31',
                label: '單選3'
              }]
            }).backgroundColor('#fff').margin(10).borderRadius(5)
            DiygwRadio({
              value: $radio,
              itemWidth:'50%',
              valueField: 'value1',
              labelField: 'label1',
              list: [{
                value1: 'radio1',
                label1: '單選1'
              }, {
                value1: 'radio2',
                label1: '單選2'
              }, {
                value1: 'radio3',
                label1: '單選3'
              }]
            }).backgroundColor('#fff').margin(10).borderRadius(5)
            DiygwRadio({
              value: $radio,
              itemWidth:'100%',
              valueField: 'value1',
              labelField: 'label1',
              list: [{
                value1: 'radio1',
                label1: '單選1'
              }, {
                value1: 'radio2',
                label1: '單選2'
              }, {
                value1: 'radio3',
                label1: '單選3'
              }]
            }).backgroundColor('#fff').margin(10).borderRadius(5)