HarmonyOS list foreach组件怎样更改item?

点击item进行下载 下载进度更新 对应的item展示进度条

使用@Observed和ObjectLink item数据变了 但是不更新

import { getColorWithOpacity } from 'comComponent/Index'
import QDReadFormatting from '../../breaktext/QDReadFormatting'
import { getLineHeight, getPageAnim, getPagePadding, setLineHeight, setPagePadding } from '../../config/ReadConfig'
import { ReadFont } from '../../config/ReadSetting'
import { QDReadEngine } from '../../controller/QDReadEngine'
import { setReadFont } from '../../font/ReadFontManager'
import ReadThemeLoader from '../../theme/ReadThemeLoader'
import { readLogDebug } from '../../utils/ReadLogger'

@Component
export struct ReadMenuFontPanel {
  @Link isShowFontPanel: boolean
  //页边距
  @State readPagePadding: number = 0
  //行高
  @State readPageLineHeight: number = 0
  @Consume('readEngine') readEngine: QDReadEngine
  @Consume('fontColor') fontColor: string
  @Consume('bgColor') bgColor: string
  @Consume('highLightColor') highLightColor: string
  @Consume('tintColor') tintColor: string
  @Consume('backgroundLightColor') backgroundLightColor: string
  @Consume('pageImage') pixelMap: PixelMap
  @State private fontArray: ReadFontList = []

  aboutToAppear() {
    this.fontArray = [
      new ReadFontEntity("系统文字", ReadFont.FONT_SYSTEM),
      new ReadFontEntity("悠哉字体", ReadFont.FONT_YOU_ZAI),
      new ReadFontEntity("霞鹜文楷", ReadFont.FONT_LXGW),
      new ReadFontEntity("思源宋体", ReadFont.FONT_SOURCE_HAN),
      new ReadFontEntity("汉仪正圆", ReadFont.FONT_ZHENG_YUAN),
      new ReadFontEntity("汉仪中黑TS", ReadFont.FONT_ZHONG_HEI)
    ]
    // '朱雀仿宋', '悠哉字体', '霞鹜文楷', '思源宋体'
    this.readPagePadding = getPagePadding()
    this.readPageLineHeight = getLineHeight()

  }

  async onReadConfigChanged() {
    const topHeight = AppStorage.get('WindowInsetTopHeight') as number
    QDReadFormatting.initReadConfig(topHeight, 0, 0)
    this.readEngine?.reloadCurChapter()
  }

  build() {
    Column() {

      RelativeContainer() {
        Image($r('app.media.svg_jiantou_xia'))
          .height(24)
          .width(24)
          .id('ivBack')
          .alignRules({
            top: { anchor: '__container__', align: VerticalAlign.Top },
            bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
            left: { anchor: '__container__', align: HorizontalAlign.Start }
          })
          .onClick(() => {
            this.isShowFontPanel = !this.isShowFontPanel
          })
          .fillColor(getColorWithOpacity(this.fontColor, 0.7))

        Text('文字设置')
          .fontColor(getColorWithOpacity(this.fontColor, 0.7))
          .alignRules({
            top: { anchor: '__container__', align: VerticalAlign.Top },
            bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
            middle: { anchor: '__container__', align: HorizontalAlign.Center }
          })
          .fontSize(18)
      }.width('100%').height(56)


      Divider()
        .width('100%')
        .height(px2vp(1))
        .backgroundColor(getColorWithOpacity(this.fontColor, 0.12))

      Row({ space: 4 }) {
        RelativeContainer() {
          Text('边距')
            .fontColor(getColorWithOpacity(this.fontColor, 0.7))
            .align(Alignment.Start)
            .fontSize(12)
            .margin({ top: 6, left: 8 })
            .id('tvPadding')
            .alignRules({
              top: { anchor: '__container__', align: VerticalAlign.Top },
              left: { anchor: '__container__', align: HorizontalAlign.Start }
            })
          RelativeContainer() {
            Slider({
              value: this.readPagePadding,
              max: 5,
              style: SliderStyle.InSet,
              step: 1
            })
              .trackColor(getColorWithOpacity(this.fontColor, 0.08))
              .selectedColor(getColorWithOpacity(this.fontColor, 0.16))
              .blockColor(this.backgroundLightColor)
              .layoutWeight(1)
              .trackThickness(36)
              .stepSize(5)
              .borderRadius(39)
              .blockSize({ width: 32, height: 32 })
              .trackBorderRadius(39)
              .onChange((value: number, mode: SliderChangeMode) => {
                if (mode == SliderChangeMode.End || mode == SliderChangeMode.Click) {
                  setPagePadding(value)
                  this.onReadConfigChanged()
                }
              })
              .alignRules({
                left: { anchor: '__container__', align: HorizontalAlign.Start },
                right: { anchor: '__container__', align: HorizontalAlign.End },
                top: { anchor: '__container__', align: VerticalAlign.Top },
                bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
              })
              .margin({ left: 2 })
              .id('leftSlider')
              .height(36)

            Text('窄')
              .fontSize(14)
              .alignRules({
                left: { anchor: '__container__', align: HorizontalAlign.Start },
                top: { anchor: '__container__', align: VerticalAlign.Top },
                bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
              })
              .margin({ left: 16 })
              .fontColor(getColorWithOpacity(ReadThemeLoader.fontColor, 0.36))

            Text('宽')
              .fontSize(14)
              .alignRules({
                right: { anchor: '__container__', align: HorizontalAlign.End },
                top: { anchor: '__container__', align: VerticalAlign.Top },
                bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
              })
              .margin({ right: 16 })
              .fontColor(getColorWithOpacity(ReadThemeLoader.fontColor, 0.36))
          }
          .layoutWeight(1)
          .height(36)
          .margin({ top: 6 })
          .alignRules({
            top: { anchor: 'tvPadding', align: VerticalAlign.Bottom },
            left: { anchor: '__container__', align: HorizontalAlign.Start }
          })
        }
        .layoutWeight(1)
        .height(72)

        RelativeContainer() {
          Text('行距')
            .fontColor(getColorWithOpacity(this.fontColor, 0.7))
            .fontSize(12)
            .id('tvLineHeight')
            .margin({ top: 6, left: 2 })
            .alignRules({
              top: { anchor: '__container__', align: VerticalAlign.Top },
              left: { anchor: '__container__', align: HorizontalAlign.Start }
            })
          RelativeContainer() {
            Slider({
              value: this.readPageLineHeight,
              max: 7,
              style: SliderStyle.InSet,
              step: 1
            })
              .trackColor(getColorWithOpacity(this.fontColor, 0.08))
              .selectedColor(getColorWithOpacity(this.fontColor, 0.16))
              .blockColor(this.backgroundLightColor)
              .layoutWeight(1)
              .trackThickness(36)
              .stepSize(5)
              .borderRadius(39)
              .id('rightSlider')
              .blockSize({ width: 32, height: 32 })
              .trackBorderRadius(39)
              .onChange((value: number, mode: SliderChangeMode) => {
                if (mode == SliderChangeMode.End || mode == SliderChangeMode.Click) {
                  setLineHeight(value)
                  this.onReadConfigChanged()
                }
              })
              .alignRules({
                left: { anchor: '__container__', align: HorizontalAlign.Start },
                right: { anchor: '__container__', align: HorizontalAlign.End },
                top: { anchor: '__container__', align: VerticalAlign.Top },
                bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
              })
              .margin({ left: 2 })
              .id('leftSlider')
              .height(36)

            Text('小')
              .fontSize(14)
              .alignRules({
                left: { anchor: '__container__', align: HorizontalAlign.Start },
                top: { anchor: '__container__', align: VerticalAlign.Top },
                bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
              })
              .margin({ left: 16 })
              .fontColor(getColorWithOpacity(ReadThemeLoader.fontColor, 0.36))

            Text('大')
              .fontSize(14)
              .alignRules({
                right: { anchor: '__container__', align: HorizontalAlign.End },
                top: { anchor: '__container__', align: VerticalAlign.Top },
                bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
              })
              .margin({ right: 16 })
              .fontColor(getColorWithOpacity(ReadThemeLoader.fontColor, 0.36))
          }
          .height(36)
          .margin({ top: 6 })
          .alignRules({
            top: { anchor: 'tvLineHeight', align: VerticalAlign.Bottom },
            left: { anchor: '__container__', align: HorizontalAlign.Start }
          })
          .layoutWeight(1)
          .height(36)
        }
        .layoutWeight(1)
        .height(72)
      }
      .width('100%')
      .height(72)
      .margin({ top: 8 })

      List({ space: 8 }) {
        ForEach(this.fontArray, (item: ReadFontEntity) => {
          ListItem() {
            Row() {
              Text(item.text)
                .fontSize(14)
                .fontColor(this.fontColor)
                .margin({ left: 12 })
                .align(Alignment.Start)

              if (item.receivedSize !== undefined && item.receivedSize > 0) {
                Progress({ value: item.receivedSize, total: item.totalSize, type: ProgressType.Ring })
                  .width(100).color(ReadThemeLoader.highLight)
                  .margin({ left: 12 })
                  .align(Alignment.End)
              }
            }
            .width('100%')
            .borderRadius(6)
            .height(40)
            .backgroundColor(getColorWithOpacity(this.fontColor, 0.04))
            .onClick(() => {
              setReadFont(getContext(this), item.type, {
                onSuccess: () => {
                  this.readEngine.reloadCurChapter()
                  item.receivedSize = 0
                  item.totalSize = 0
                },
                progress: (receivedSize: number, totalSize: number) => {
                  item.receivedSize = receivedSize
                  item.totalSize = totalSize
                  readLogDebug("正在下载 : receivedSize " + receivedSize + " totalSize : " + totalSize)
                },
                onError: (errorMsg: string) => {
                  readLogDebug("下载失败 : " + errorMsg)
                }
              })
            })
          }
        }, (item: ReadFontEntity) => item.text + item.receivedSize + item.type)
      }
      .listDirection(Axis.Vertical)
      .margin({ left: 8, right: 8, top: 12 })
      .lanes(2, 8)
    }
    .width('100%')
    .backgroundColor(this.backgroundLightColor)
    .padding({ left: 8, right: 8, bottom: 22 })
    .onClick(() => {
    })
    .height(318)
  }
}

@Observed
class ReadFontList extends Array<ReadFontEntity> {
}

@Observed
class ReadFontEntity {
  text: string = ""
  type: number = 0
  size?: string
  isDownload?: boolean
  receivedSize?: number
  totalSize?: number

  constructor(text: string, type: number = 0, size?: string, isDownload?: boolean, receivedSize?: number, totalSize?: number) {
    this.text = text
    this.type = type
    this.size = size
    this.isDownload = isDownload
    this.receivedSize = receivedSize
    this.totalSize = totalSize
  }
}
阅读 394
1 个回答

foreach遍历出来的item应该用一个自定义组件来接受,传递下去,像文档中的方式,如图所示:

这个ClassA[]是个数组,foreach拿出来了item,然后定义了一个自定义组件ViewA,iewA中有一个@ObjectLink来接收传进来的item,是以这种方式。

对应提供的代码,在foreach中,这个progress应该写在一个自定义组件中,自定义组件来接受item

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进