“答开发者问”之HarmonyOS鸿蒙Next技术问题解析 第11期

“答开发者问”之HarmonyOS鸿蒙Next技术问题解析 第11期 向所有参与社区互助的开发者致以最诚挚的感谢!

特别感谢本期优质答复贡献者:@冉冉同学、@灯下芯、@todayisall

社区的蓬勃发展,离不开每一位积极参与者的贡献。本期“答开发者问”栏目,精选自广大热心开发者针对提问帖所贡献的众多优质答复之中。它们不仅是智慧与经验的璀璨结晶,更是“众人拾柴火焰高”这一真理的生动体现。

在此,我们由衷地感谢每一位热心参与、乐于分享的开发者,是你们的热情与智慧,让这个社区充满了生机与活力,每一次的解答都是对技术探索精神的最好诠释。同时,我们也诚挚邀请更多的开发者加入到这场智慧碰撞的盛宴中来。无论是抛出难题寻求解答,还是慷慨解囊分享经验,您的每一份参与都将为鸿蒙开发者社区注入新的活力,推动我们共同前行,在技术的海洋中扬帆远航。

本期问题如下:

  1. 如何实现多主题下正常模式和深色模式适配?
  2. 局部@Builder传参未生效问题?
  3. 如何在二维码的中间加个头像?
  4. list怎么更新单个item的ui?
  5. 当前HarmonyOS支持画中画和悬浮窗吗?

答开发者问系列汇总:

“答开发者问”系列汇总(持续更新中…)

往期问题回顾:

“答开发者问”之HarmonyOS技术问题解析 第1期-华为开发者问答 | 华为开发者联盟 (huawei.com)

“答开发者问”之HarmonyOS技术问题解析 第2期-华为开发者问答 | 华为开发者联盟 (huawei.com)

“答开发者问”之HarmonyOS技术问题解析 第3期-华为开发者问答 | 华为开发者联盟 (huawei.com)

“答开发者问”之HarmonyOS技术问题解析 第4期-华为开发者问答 | 华为开发者联盟 (huawei.com)

“答开发者问”之HarmonyOS技术问题解析 第5期-华为开发者问答 | 华为开发者联盟 (huawei.com)

“答开发者问”之HarmonyOS技术问题解析 第6期-华为开发者问答 | 华为开发者联盟 (huawei.com)

“答开发者问”之HarmonyOS技术问题解析 第7期-华为开发者问答 | 华为开发者联盟 (huawei.com)

“答开发者问”之HarmonyOS技术问题解析 第8期-华为开发者问答 | 华为开发者联盟 (huawei.com)

“答开发者问”之HarmonyOS技术问题解析 第9期-华为开发者问答 | 华为开发者联盟 (huawei.com)

“答开发者问”之HarmonyOS技术问题解析 第10期-华为开发者问答 | 华为开发者联盟 (huawei.com)

注意:

开发者小伙伴们,规范提问,高效沟通!更快得到问题答案的秘诀来啦,点击链接直达


更多关于“答开发者问”之HarmonyOS鸿蒙Next技术问题解析 第11期的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

问题五:当前HarmonyOS支持画中画和悬浮窗吗?

HarmonyOS当前支持画中画和悬浮窗吗?

解决方案:

关于悬浮窗模式:

  • 需要申请且目前只有2in1设备才能申请。
  • 需要通过应用市场申请ACL权限ohos.permission.SYSTEM_FLOAT_WINDOW。
  • 需要在配置文件中添加权限说明,从而允许应用使用悬浮窗的能力。

使用ACL的签名配置指导:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V14/ide-signing-V14#section9786111152213

目前只推荐画中画模式,开发指南:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V14/pipwindow-overview-V14?catalogVersion=V14

原链接:

支持画中画模式和悬浮窗吗?-华为开发者问答 | 华为开发者联盟 (huawei.com)

更多关于“答开发者问”之HarmonyOS鸿蒙Next技术问题解析 第11期的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


问题四:list怎么更新单个item的ui?

问题描述:

@Observed
class TopicBean {
  public count: number = 0;

  constructor(count: number) {
    this.count = count;
  }
}

@Component
struct ObjectLinkChild {
  @ObjectLink testNum: TopicBean;

  build() {
    Text(`ObjectLinkChild testNum ${this.testNum.count}`)
      .onClick(() => {
        this.testNum.count = 40;
      })
  }
}

@Entry
@Component
struct ParentTest {
  @State topics: Array<TopicBean> = new Array()

  aboutToAppear(): void {
    this.topics.push(new TopicBean(10))
  }

  build() {
    Column() {
      Text(`Parent testNum ${this.topics[0].count}`)
        .onClick(() => {
          this.topics[0].count += 1;
        })

      ObjectLinkChild({ testNum: this.topics[0] })
    }
  }
}

建议使用V2状态管理,V2中直接topics[0].count = 6即可。

原链接:

list怎么更新单个item的ui-华为开发者问答 | 华为开发者联盟 (huawei.com)

问题三:如何在二维码的中间加个头像?

问题描述: 如果要像微信那样在二维码的中间加个头像应该怎么做,是否有对应API?

解决方案: 可以通过stack布局,将Image组件放在QRCode组件上实现,通过设置image合适大小,不会影响QRCode识别,示例代码如下:

@Entry
@Component
struct QRCodeTest {
  private value: string = 'hello world';

  build() {
    Stack() {
      QRCode(this.value)
        .width(200)
        .height(200)
      Image($r('app.media.app_icon'))
        .height(50)
        .width(50)
    }
    .height('100%')
    .width('100%')
  }
}

原链接: 如果要在二维码的中间加个头像(图片)怎么做-华为开发者问答 | 华为开发者联盟 (huawei.com)

问题二:局部@Builder传参未生效问题?

问题描述:

demo代码如下:

// xxx.ets
@Entry
@Component
struct TabsExample {
  @State fontColor: string = '#182431'
  @State selectedFontColor: string = '#007DFF'
  @State currentIndex: number = 0
  @State selectedIndex: number = 0
  private controller: TabsController = new TabsController()
  @State num1:number=9
  @State num2:number=59
  @State num3:number=109

  [@Builder](/user/Builder) tabBuilder(index: number, name: string,num:number) {
    Column() {
      Badge({
        count:num,
        style: { fontSize: 10, badgeSize: 1 },
        position: { x: 10, y: -10 },
     }) {
        Text(name)
          .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
          .fontSize(16)
          .fontWeight(this.selectedIndex === index ? 500 : 400)
          .lineHeight(22)
      }

      Divider()
        .strokeWidth(2)
        .color('#007DFF')
        .opacity(this.selectedIndex === index ? 1 : 0)
    }.width('100%')
  }
  [@Builder](/user/Builder) TabsBuilder(){
    Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
      TabContent() {
        Column().width('100%').height('100%').backgroundColor('#00CB87')
      }.tabBar(this.tabBuilder(0, 'green',this.num1))

      TabContent() {
        Column().width('100%').height('100%').backgroundColor('#007DFF')
      }.tabBar(this.tabBuilder(1, 'blue',this.num2))

      TabContent() {
        Column().width('100%').height('100%').backgroundColor('#FFBF00')
      }.tabBar(this.tabBuilder(2, 'yellow',this.num3))

    }
    .vertical(false)
    .barMode(BarMode.Fixed)
    .barWidth(360)
    .barHeight(56)
    .animationDuration(400)
    .onChange((index: number) => {
      // currentIndex控制TabContent显示页签
      this.currentIndex = index
    })
    .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
      if (index === targetIndex) {
        return
      }
      // selectedIndex控制自定义TabBar内Image和Text颜色切换
      this.selectedIndex = targetIndex
    })
    .width(360)
    .height(296)
    .margin({ top: 52 })
    .backgroundColor('#F1F3F5')
  }

  build() {
    Column() {
      this.TabsBuilder()
    }.width('100%')
  }
}

当前问题是num1、num2、num3这三个参数初始时通过直接赋值的方式的话能在Badge里面显示,但是变化后重新获取到的数据不会刷新UI显示。

解决方案:

interface temp {
  index: number,
  name: string,
  num: number
}

@Entry
@Component
struct BuilderTest {
  // xxx.ets
  @State fontColor: string = '#182431'
  @State selectedFontColor: string = '#007DFF'
  @State currentIndex: number = 0
  @State selectedIndex: number = 0
  private controller: TabsController = new TabsController()
  @State num1: number = 9
  @State num2: number = 59
  @State num3: number = 69

  [@Builder](/user/Builder)
  tabBuilder(temp: temp) {
    Column() {
      Badge({
        count: temp.num,
        style: { fontSize: 10, badgeSize: 1 },
        position: { x: 10, y: -10 },
      }) {
        Text(temp.name)
          .fontColor(this.selectedIndex === temp.index ? this.selectedFontColor : this.fontColor)
          .fontSize(16)
          .fontWeight(this.selectedIndex === temp.index ? 500 : 400)
          .lineHeight(22)
      }

      Divider()
        .strokeWidth(2)
        .color('#007DFF')
        .opacity(this.selectedIndex === temp.index ? 1 : 0)
    }.width('100%')
  }

  [@Builder](/user/Builder)
  TabsBuilder() {
    Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
      TabContent() {
        Column() {
          Button("控制blue数字").onClick(() => {
            this.num2++
          })
        }.width('100%').height('100%').backgroundColor('#00CB87')
      }.tabBar(this.tabBuilder({
        index: 0,
        name: 'green',
        num: this.num1
      }))

      TabContent() {
        Column() {
          Button("控制yellow数字").onClick(() => {
            this.num3++
          })
        }.width('100%').height('100%').backgroundColor('#007DFF')
      }.tabBar(this.tabBuilder({
        index: 1,
        name: 'blue',
        num: this.num2
      }))

      TabContent() {
        Column() {
          Button("控制green数字").onClick(() => {
            this.num1++
          })
        }.width('100%').height('100%').backgroundColor('#FFBF00')
      }.tabBar(this.tabBuilder({
        index: 2,
        name: 'yellow',
        num: this.num3
      }))

    }
    .vertical(false)
    .barMode(BarMode.Fixed)
    .barWidth(360)
    .barHeight(56)
    .animationDuration(400)
    .onChange((index: number) => {
      // currentIndex控制TabContent显示页签
      this.currentIndex = index
    })
    .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
      if (index === targetIndex) {
        return
      }
      // selectedIndex控制自定义TabBar内Image和Text颜色切换
      this.selectedIndex = targetIndex
    })
    .width(360)
    .height(296)
    .margin({ top: 52 })
    .backgroundColor('#F1F3F5')
  }

  build() {
    Column() {
      this.TabsBuilder()
    }.width('100%')
  }
}

原链接:

[急急急!!! 局部@Builder传参问题-华为开发者问答 | 华为开发者联盟 (huawei.com)](https://developer.huawei.com/consumer/cn/forum/topicview?tid=0204167415686544462&fid=0109140870620153026)

问题一:如何实现多主题下正常模式和深色模式适配?

问题描述:

在适配多主题且每个主题都需要适配正常模式和深色模式,颜色需要怎么处理?比如一个背景颜色颜色要使用主题色 A主题 正常:#84BD00 深色:#FF5F00,另一个使用B主题正常:#00D7FF 深色:#FF0082。

解决方案:

可以抽出所有主题中公共的颜色,正常模式颜色配置在base>element>color.json中

{
  "name": "theme_color",
  "value": "#84BD00"
},
{
  "name": "themeSec_color",
  "value": "#00D7FF"
}

深色模式颜色配置在dark>element>color.json中

{
  "name": "theme_color",
  "value": "#FF5F00"
},
{
  "name": "themeSec_color",
  "value": "#FF0082"
}

采用多主题动态设置的方式来实现目标,参考demo:

import { CustomColors, CustomTheme } from '@kit.ArkUI'

class AppColors implements CustomColors {
  fontPrimary: ResourceColor = $r('app.color.theme_color')
  backgroundEmphasize: ResourceColor = $r('app.color.theme_color')
}

class AppColorsSec implements CustomColors {
  fontPrimary: ResourceColor = $r('app.color.themeSec_color')
  backgroundEmphasize: ResourceColor = $r('app.color.themeSec_color')
}

class AppTheme implements CustomTheme {
  public colors: AppColors = new AppColors()
}

class AppThemeSec implements CustomTheme {
  public colors: AppColors = new AppColorsSec()
}

@Entry
@Component
struct DisplayThemePage {
  @State customTheme: CustomTheme = new AppTheme()
  @State message: string = '设置应用局部页面自定义主题风格'
  count = 0;

  build() {
    WithTheme({ theme: this.customTheme }) {
      Row() {
        Column() {
          Text('WithTheme')
            .fontSize(30)
            .margin({ bottom: 10 })
          Text(this.message)
            .margin({ bottom: 10 })
          Button('change theme').onClick(() => {
            this.count++;
            if (this.count > 1) {
              this.count = 0;
            }
            switch (this.count) {
              case 0:
                this.customTheme = new AppTheme();
                break;
              case 1:
                this.customTheme = new AppThemeSec();
                break;
            }
          })
        }
        .width('100%')
      }
      .height('100%')
      .width('100%')
    }
  }
}

原链接:

多主题适配 color文件是否可以选择使用-华为开发者问答 | 华为开发者联盟 (huawei.com)

在“答开发者问”之HarmonyOS鸿蒙Next技术问题解析第11期中,主要聚焦于鸿蒙Next的核心技术更新与开发者常见问题。本期重点解析了分布式任务调度、设备虚拟化、以及跨设备协同等关键技术,帮助开发者更好地理解和应用鸿蒙Next的新特性。同时,针对开发者在实际开发过程中遇到的性能优化、API调用等问题,提供了详细的解决方案和最佳实践建议,助力开发者提升应用开发效率与用户体验。

回到顶部