HarmonyOS鸿蒙Next中表格单元格颜色不更新

HarmonyOS鸿蒙Next中表格单元格颜色不更新

创建了一个3列的表格,其中第3列为颜色,不同单元格用不同的颜色填充

当单击某个单元格时,弹出颜色选择对话框,可以选择颜色,然后要用新的颜色填充这个单元格

现在是表格中的数据(包括颜色)更新了,但是单元格的填充颜色不更新,是怎么回事?

主文件的代码片段如下,详细的可以看附件

@Entry
@Component
struct Index {
  @State tableData: TableData  = new TableData()
  
  @State selectedRowIndex: number = -1; // 记录当前选中的行索引

  @State color_picked: string = '#ff0000';

  colorPickDialogController: CustomDialogController | null = new CustomDialogController({
    builder: ColorPickDialog({
      selected_color: this.color_picked,
      onColorSelected:(newColor: string) => {
        this.color_picked = newColor;
        console.log('confirm后 controller 返回的颜色:', this.color_picked)
      //   颜色正确返回
      //   对tableData进行更行
        if (this.selectedRowIndex >= 0 && this.selectedRowIndex < this.tableData.rows.length) {
          let value = this.tableData.rows[this.selectedRowIndex].mass_ecc;
          this.tableData.setRowData(this.selectedRowIndex, value,newColor);
          this.tableData = this.tableData; // 触发UI更新
          this.tableData.dump();
          console.log('已更新第', this.selectedRowIndex, '行的颜色为:', newColor);
        }
      // }
    }),
    alignment: DialogAlignment.Center,
    width: '80%',
    cornerRadius: 15,
    backgroundColor: $r('sys.color.background_primary')
  })
  
  build() {
    Column() {
      // 表头
      Row() {
        Text('组别号').width('30%').textAlign(TextAlign.Center)
        Text('质量g').width('40%').textAlign(TextAlign.Center)
        Text('颜色').width('30%').textAlign(TextAlign.Center)
      }
      .padding(10)
      .backgroundColor(Color.White)

      // 表格内容
      List({ space: 5 }) {
        ForEach(this.tableData.rows,
          (row: TableRow) => {
          ListItem() {
            Row() {
              // 序号列 (P+数字)
              Text(`P${row.bolt_sn}`)
                .width(100)
                .height(50)
                .textAlign(TextAlign.Center)
                .fontSize(16)

              // 数值列
              TextInput({ text: row.mass_ecc.toString() })
                .width(150)
                .height(50)
                .type(InputType.Number)
                .textAlign(TextAlign.Center)
                .inputFilter('[0-9.]', (value: string) => {
                  const regex = /^[0-9]*\.?[0-9]*$/;
                  return regex.test(value);
                })
                .enterKeyType(EnterKeyType.Done)
                .onChange(( value:string) => {
                  const newValue = (value === '' || value === '.') ? 0 : parseFloat(value) || 0;
                  this.tableData.setRowData(row.bolt_sn - 1, newValue, row.color);
                  this.tableData.dump()
                })

              // 颜色列
              Text(row.color)
                .width(150)
                .height(50)
                .textAlign(TextAlign.Center)
                .backgroundColor(row.color)
                .onAppear(()=>{
                  console.log('单元格渲染,row:', this.selectedRowIndex, '颜色' ,row.color);
                }
                )
                .onClick(() => {
                  this.selectedRowIndex = row.bolt_sn - 1; // 保存行索引
                  this.color_picked = row.color; // 设置当前颜色
                  this.colorPickDialogController?.open()
                })
            }
            .width('90%')
            .borderRadius(5)
            .backgroundColor('#ffffff')
            .shadow({ radius: 2, color: '#888', offsetX: 1, offsetY: 1 })
          }.key(row.bolt_sn.toString())
        },
          (row: TableRow) => row.bolt_sn.toString()
        )
      }
      .width('100%')
      .height(300)
      .margin({ top: 10 })
      .layoutWeight(1)

      // 新增控制行
      Row() {
        Text('螺钉组别数')
          .width('30%')
          .textAlign(TextAlign.Center)

        TextInput({ text: this.balanceBoltNum.toString() })
          .width('40%')
          .type(InputType.Number)
          .maxLength(2)
          .enterKeyType(EnterKeyType.Done)
          .enabled(this.editable)
          .onChange((value: string) => {
            const num = parseInt(value)
            // 螺钉组别数不大于12组
            if (!isNaN(num) && num > 0 && num <= 12) {
              this.balanceBoltNum = num
            }
          })

        Button(this.buttonText)
          .width('30%')
          .onClick(() => {
            if (this.editable) {
              // 保存操作
              const newLength = Math.min(Math.max(this.balanceBoltNum, 1), 12) // 限制1-20行
              this.buttonText = '编辑'
              this.editable = false
              console.log('new bolt Num = ', this.balanceBoltNum)
              console.log('need to change the table')
              if (this.balanceBoltNum > 0 && this.balanceBoltNum <= 12) {
                // update table
                this.tableData.adjustRowCount(this.balanceBoltNum)
                this.tableData.dump()
              }
            } else {
              // 进入编辑状态
              this.buttonText = '保存'
              this.editable = true
            }
          })
      }
      .padding(10)
      .backgroundColor('#F5F5F5')

    }
}

TableData类的定义如下

@Observed
export class TableRow {
  bolt_sn: number
  public mass_ecc: number
  public color: string

  constructor(index: number = 1, value: number = 50.0, color: string = '#F80000') {
    this.bolt_sn = index
    this.mass_ecc = value
    this.color = color
  }
}

@Observed
export class TableData {
  rows: Array<TableRow> = [];

  constructor() {
    // 初始化5行数据
    this.adjustRowCount(5)
  }

  // 调整行数(1-12)
  adjustRowCount(newCount: number) {

    const currentCount = this.rows.length;
    if (newCount === currentCount) {
      return;
    }

    // 创建全新的数组而不是修改原数组
    const newRows: Array<TableRow> = [];

    // 保留现有行数据
    const rowsToKeep = Math.min(currentCount, newCount);
    for (let i = 0; i < rowsToKeep; i++) {
      newRows.push(new TableRow(
        i + 1,
        this.rows[i].mass_ecc,
        this.rows[i].color
      ));
    }

    // 大于当前行数,则添加行
    if (newCount > currentCount && newCount <= 12)  {
      for (let i = currentCount; i < newCount; i++) {
        newRows.push(new TableRow(
          i+1,
          me_array[i],
          colorOptions[i]
        ))
      }
    }
    // 确保行数在1-12之间
    newCount = Math.max(1, Math.min(newCount, 12))
    // 确保序号正确
    newRows.forEach((row, index) => {
      row.bolt_sn = index + 1
    })

    // 必须创建全新的数组引用
    this.rows = newRows;

  }

  // 设置某行的数据
  setRowData(index: number, value: number, color: string) {
    if (index < 0 || index >= this.rows.length) {
      return;
    }
    // 创建新数组
    const newRows = [...this.rows];
    newRows[index] = new TableRow(
      index + 1,
      value,
      color
    );
    this.rows = newRows;
  }

  // 通过console打印所有row的数据

  dump() {
    this.rows.forEach((row, index) => {
      console.log(`Row ${index + 1}: SN=${row.bolt_sn}, ME=${row.mass_ecc}, Color=${row.color}`)
    })
  }
}

颜色选择对话框 colorpickdialog参考了如下工作:https://developer.huawei.com/consumer/cn/blog/topic/03167420824634034

我上传完整的项目还上传不了,上传文件限制太死了


更多关于HarmonyOS鸿蒙Next中表格单元格颜色不更新的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS鸿蒙Next中,表格单元格颜色不更新可能是由以下原因导致:

  1. 数据绑定未正确触发:确保@State@Link修饰的变量变更后触发了UI刷新
  2. 组件未设置id属性:动态样式更新需要为Column/Row组件设置唯一id
  3. 颜色值格式问题:确认颜色值使用Resource格式($r(‘app.color.xxx’))或合法ARGB值
  4. 布局更新限制:检查是否在禁用状态(enabled(false))下尝试了样式更新

典型解决方案应检查数据绑定逻辑和组件标识设置,而非直接操作DOM样式。

更多关于HarmonyOS鸿蒙Next中表格单元格颜色不更新的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


从代码来看,颜色不更新的问题可能出在以下几个方面:

  1. 数据更新方式问题:
  • 虽然调用了setRowData方法更新了数据,但TableRow类使用了@Observed装饰器,而TableData类也使用了@Observed装饰器。这种情况下,需要确保每次更新时都创建新的对象引用。
  1. 状态管理问题:
  • colorPickDialogControlleronColorSelected回调中,虽然更新了tableData,但可能没有正确触发UI刷新。尝试修改为:
    this.tableData = {...this.tableData}; // 创建新引用
    
  1. 单元格渲染问题:
  • 确保Text组件的backgroundColor属性绑定了正确的row.color值。从代码看绑定是正确的,但可以尝试在onAppear中添加日志确认实际渲染值。
  1. 强制刷新问题:
  • 当前使用了this.tableData = this.tableData来触发更新,这种方式可能不会生效。建议改为:
    this.tableData = JSON.parse(JSON.stringify(this.tableData));
    

建议优先检查第1点和第2点,确保数据更新时创建了新的对象引用,这是ArkUI框架状态管理的核心机制。

回到顶部