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

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

特别感谢本期优质答复贡献者:@小夜呆呆、@冉冉同学

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

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

本期问题如下:

  1. 如何在自定义类中展示带图片的toast?
  2. 怎么使用colorFilter修改图片的颜色?
  3. 如何实现一个气泡聊天框?
  4. 要实现promptAction.openCustomDialog的弹窗关闭动画完成后蒙层才消失,应该怎么做?
  5. scroll和tabs关联,想让tabBar的标签可以划出屏幕,除了自定义tab以外还有其他办法吗?

答开发者问系列汇总:

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

往期问题回顾:

"答开发者问"之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鸿蒙Next技术问题解析 第8期的实战教程也可以访问 https://www.itying.com/category-93-b0.html

8 回复

问题一:如何在自定义类中展示带图片的toast?

问题描述: 我想在自定义类的方法中调用自定义组件的toast展示,怎么实现呢? 代码如下图,在action方法中,通过接收toast的参数属性值,传给UI组件,最终展示需要的toast效果。这里官方提供的promptAction.showToast是可以正常显示的,但自定义组件不知道应该如何展示?

解决方案: ArkUI中的自定义组件展示是需要window的,比如所有界面都是EntryAbility中的windowStage.loadContent()执行后,才被展示的。单个页面内部也有UIContext来执行toast/dialog的操作。 可以将UIContext作为参数传入action方法实现,示例demo如下,其余业务逻辑可以自行补充:

import { ComponentContent, UIContext, window } from '[@kit](/user/kit).ArkUI'
import { hilog } from '[@kit](/user/kit).PerformanceAnalysisKit'

class FakeToastManager {
  private currentContent: ComponentContent<Object> | undefined = undefined

  action(uiContext: UIContext) {
    this.currentContent = new ComponentContent<string>(uiContext, wrapBuilder(BuilderFake), '我是传递的内容')
    uiContext.getPromptAction().openCustomDialog(this.currentContent, {
      autoCancel: false,
      alignment: DialogAlignment.Bottom,
      isModal: false,
      offset: {
        dx: 0,
        dy: '-90vp'
      }
    })
    setTimeout(() => {
      uiContext.getPromptAction().closeCustomDialog(this.currentContent)
    }, 2000)
  }

  // Preview不可用,需要运行在模拟器跟真机
  actionFake() {
    window.getLastWindow(getContext()).then((windowClass) => {
      let uiContext = windowClass.getUIContext()
      this.action(uiContext)
    })
  }
}

[@Entry](/user/Entry)
[@ComponentV2](/user/ComponentV2)
struct Index {
  private fakeToast: FakeToastManager = new FakeToastManager()

  build() {
    Navigation() {

      Column() {
        Button('Fake Toast').onClick(() => {
          this.fakeToast.action(this.getUIContext())
        })
        Blank()
        Text('在fake toast展示时不影响界面点击').onClick(() => {
          hilog.debug(0x000000, 'rainrain', 'click ---')
        })
      }.size({ width: '100%', height: '100%' })

    }.size({ width: '100%', height: '100%' })

  }
}

[@Builder](/user/Builder)
function BuilderFake(text: string) {
  FakeToast({ text: text })
}

[@ComponentV2](/user/ComponentV2)
struct FakeToast {
  [@Param](/user/Param) text: string = ''

  build() {
    Column() {
      Text('我是假Toast')
      Text(this.text)
    }.backgroundColor(Color.Green)
  }
}
``>

原链接:
[如何在普通类中调用自定义组件,并正常展示-华为开发者问答 | 华为开发者联盟 (huawei.com)](https://developer.huawei.com/consumer/cn/forum/topic/0203171882627439025?fid=0101587866109860105&pid=0302171892804342012)

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


问题五:scroll和tabs关联,想让tabBar的标签可以划出屏幕,除了自定义tab以外还有其他办法吗?

问题描述: 如图,除了自定义tab,有没有办法实现tabBar的标签可以划出屏幕?

解决方案: 可以利用calc计算tabs的高度。高度为 100%(List高度) + barHeight高度,这样tabs实际高度超一屏,可以利用scroll滑动把titlebar滑动到上面去。只要高度计算正确,效果就符合预期。参考以下示例,代码为写死高度为60vp的情况,实际情况可以根据onVisibleAreaChange和this.getUIContext().getComponentUtils().getRectangleById()等API算出具体的高度。

补充知识——calc() 函数用于动态计算长度值。

  • 需要注意的是,运算符前后都需要保留一个空格,例如:width: calc(100% - 10px);
  • 任何长度值都可以使用calc()函数进行计算;
  • calc()函数支持 “+”, “-”, “*”, “/” 运算;
  • calc()函数使用标准的数学运算优先级规则;

原链接: scroll和tabs关联,想让tabBar的标签能划出屏幕,除了自定义外还有其他办法吗?-华为开发者问答 | 华为开发者联盟 (huawei.com)

问题四:要实现promptAction.openCustomDialog的弹窗关闭动画完成后蒙层才消失,应该怎么做?

问题描述:

使用promptAction.openCustomDialog如何实现,在打开的时候蒙层立马出现,弹窗从底部向上划出;关闭的时候弹窗先向下划出去,然后蒙层再消失?

目前只实现了打开的效果,弹窗关闭的动画好像只有在蒙层消失了才会触发。

export function openActionSheet() {
  window.getLastWindow(getContext()).then((windowClass) => {
    const uiContext = windowClass.getUIContext()
    const promptAction = uiContext.getPromptAction()

    let contentNode = new ComponentContent<boolean>(uiContext, wrapBuilder(ActionBuilder), false)
    promptAction.openCustomDialog(contentNode, {
      autoCancel: true,
      alignment: DialogAlignment.Bottom,
      transition: TransitionEffect.opacity(0.99).animation({ duration: 200 }),
      onWillDismiss: (action) => {
        animateTo({
          duration: 200,
          onFinish: () => {
            action.dismiss()
          }
        }, () => {
          contentNode.update(true)
        })
      }
    })
  })
}

@Builder
export function ActionBuilder(isEnd: boolean) {
  Column() {
    Row() {
      Text('2173781637163')
    }.width('100%').height(40)

    Row() {
      Text('2173781637163')
    }.width('100%').height(59)

    Row() {
      Text('2173781637163')
    }.width('100%').height(90)
  }
  .translate({
    y: isEnd ? '100%' : 0
  })
  .backgroundColor(Color.White)
  .transition(TransitionEffect.translate({ y: '100%' }).animation({ duration: 200 }))
}

解决方案:

可以通过onWillDismiss拦截返回事件,在事件回调中通过animateTo和update自定义关闭动画,以下示例供参考:

export function openActionSheet() {
  window.getLastWindow(getContext()).then((windowClass) => {
    const uiContext = windowClass.getUIContext()
    const promptAction = uiContext.getPromptAction()

    let contentNode = new ComponentContent<boolean>(uiContext, wrapBuilder(ActionBuilder), false)
    promptAction.openCustomDialog(contentNode, {
      autoCancel: true,
      alignment: DialogAlignment.Bottom,
      transition: TransitionEffect.opacity(0.99).animation({ duration: 200 }),
      onWillDismiss: (action) => {
        animateTo({
          duration: 200,
          onFinish: () => {
            action.dismiss()
          }
        }, () => {
          contentNode.update(true)
        })
      }
    })
  })
}

@Builder
export function ActionBuilder(isEnd: boolean) {
  Column() {
    Row() {
      Text('2173781637163')
    }.width('100%').height(40)

    Row() {
      Text('2173781637163')
    }.width('100%').height(59)

    Row() {
      Text('2173781637163')
    }.width('100%').height(90)
  }
  .translate({
    y: isEnd ? '100%' : 0
  })
  .backgroundColor(Color.White)
  .transition(TransitionEffect.translate({ y: '100%' }).animation({ duration: 200 }))
}

问题三:如何实现一个气泡聊天框?

问题描述:

气泡聊天框的内容可能是文字、或图片、或图文混排的,背景是个.9图的气泡图,如何实现呢?

解决方案:

Image组件已经提供了与点九图相同功能的API设置,可以通过设置resizable属性来设置ResizableOptions,也就是图像拉伸时可调整大小的图像选项。ResizableOptions的参数slice中有top、left、bottom和right四个属性,分别代表图片上下左右四个方向拉伸时保持不变距离。参考代码如下:

import { MeasureText } from '@kit.ArkUI'

@Component
struct ChatBubbleStretchDemo {
  @State text: string = 'Hello World Hello World Hello World Hello World'; 
  @State left: number = 10; 
  @State right: number = 10; 
  @State top: number = 10; 
  @State bottom: number = 10; 
  @State line: number = 2; 
  @State textSize: SizeOptions = MeasureText.measureTextSize({ 
    textContent: this.text 
  }); 

  build() { 
    Column() { 
      Stack() { 
        Image($r("app.media.lightBluexhdpi")) 
          .width(px2vp(Number(`${this.textSize.width}`)) < 350 ? 60 + px2vp 
          (Number(`${this.textSize.width}`)) : 350) 
          .height(this.text.length < 40 ? 50 + px2vp(Number(`${this.textSize.height}`))  
          : 50 + (px2vp(Number(`${this.textSize.height}`)) * this.line)) 
          .resizable({ 
            slice: { 
              top: this.top, 
              left: this.left, 
              bottom: this.bottom, 
              right: this.right 
            } 
          }) 
        Text(this.text) 
      } 
      .width(350) 
      .height(200) 
    } 
    .height('100%') 
    .width('100%') 
  } 
}

正常大小

左右拉伸

多行上下左右拉伸

原链接: 如何实现一个气泡聊天框 -华为开发者问答 | 华为开发者联盟 (huawei.com)

问题二:怎么使用colorFilter修改图片的颜色?

问题描述: 怎么使用colorFilter修改图片的颜色?

解决方案: 参考下面示例,通过colorFilter实现了给图像设置颜色滤镜效果:

import { drawing, common2D } from '@kit.ArkGraphics2D';

@Entry
@Component
struct ImageExample3 {
  private imageOne: Resource = $r('app.media.1');
  private imageTwo: Resource = $r('app.media.2');
  @State src: Resource = this.imageOne
  @State src2: Resource = this.imageTwo
  private ColorFilterMatrix: number[] = [1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]
  private color: common2D.Color = { alpha: 255, red: 255, green: 0, blue: 0 };
  @State drawingColorFilterFirst: ColorFilter | undefined = undefined
  @State drawingColorFilterSecond: ColorFilter | undefined = undefined
  @State drawingColorFilterThird: ColorFilter | undefined = undefined

  build() {
    Column() {
      Image(this.src)
        .width(100)
        .height(100)
        .colorFilter(this.drawingColorFilterFirst)
        .onClick(() =>{
          this.drawingColorFilterFirst = drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN);
        })

      Image(this.src2)
        .width(100)
        .height(100)
        .colorFilter(this.drawingColorFilterSecond)
        .onClick(() =>{
          this.drawingColorFilterSecond = new ColorFilter(this.ColorFilterMatrix);
        })

      //当加载图片为SVG格式时
      Image($r('app.media.test_self'))
        .width(110).height(110).margin(15)
        .colorFilter(this.drawingColorFilterThird)
        .onClick(() =>{
          this.drawingColorFilterThird = drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN);
        })
    }
  }
}

原链接: 修改图片的颜色colorFilter-华为开发者问答 | 华为开发者联盟 (huawei.com)

各位大佬们,我是一名在校大三学生,最近正在调查关于鸿蒙操作系统的用户偏好,可以请您帮我填一下问卷吗,三分钟就可以,谢谢您啦

https://www.wjx.cn/vm/h8940pT.aspx

在“答开发者问”之HarmonyOS鸿蒙Next技术问题解析第8期中,主要讨论了鸿蒙Next的技术细节和开发相关问题。鸿蒙Next是华为推出的新一代操作系统,旨在构建全场景智能生态。其核心特性包括分布式能力、微内核设计、一次开发多端部署等。

分布式能力是鸿蒙Next的显著特点,支持设备间的无缝协同。开发者可以通过分布式任务调度、分布式数据管理等技术,实现多设备间的数据共享与任务协同。微内核设计则提升了系统的安全性和稳定性,鸿蒙Next采用微内核架构,减少了内核的复杂性,增强了系统的模块化与可扩展性。

鸿蒙Next还提供了丰富的开发工具和框架,如ArkUI、ArkTS等,帮助开发者高效构建应用。ArkUI是鸿蒙的UI框架,支持声明式编程,简化了UI开发流程。ArkTS是基于TypeScript的编程语言,适用于鸿蒙应用开发,提供了类型安全和现代化的语言特性。

此外,鸿蒙Next支持一次开发多端部署,开发者只需编写一次代码,即可在手机、平板、智能穿戴等多种设备上运行应用。这大大降低了开发成本,提升了开发效率。

总体而言,鸿蒙Next通过其分布式能力、微内核设计、丰富的开发工具和一次开发多端部署等特性,为开发者提供了强大的技术支持,助力构建全场景智能生态。

在HarmonyOS鸿蒙Next技术问题解析第8期中,我们深入探讨了鸿蒙Next的核心特性与开发者常见问题。鸿蒙Next作为华为新一代操作系统,强调了分布式能力与跨设备协同,开发者需关注其应用架构、API调用及性能优化。常见问题包括如何实现多设备无缝连接、应用兼容性调试及资源高效管理。建议开发者参考官方文档,利用鸿蒙提供的开发工具链,如DevEco Studio,进行高效开发与测试,以确保应用在鸿蒙Next上的稳定运行与卓越用户体验。

回到顶部