HarmonyOS鸿蒙实战( Beta6版)基于Flex作父容器实现图文混排实践方案

170 篇文章 0 订阅
170 篇文章 0 订阅

场景描述

应用中基于原生能力实现图文混排效果有多个方案可实现,推荐使用Flex作父容器实现的方案(方案一),此方案优点在于节点数量少,结构简单。

方案一:基于Flex作父容器实现图文混排

建议基于Flex容器作为父容器实现图文混排,优点在于减少节点数量。

内部头像使用Image组件,中间部分使用Text文本组件,右边使用Text文本组件。

核心代码

Flex({ direction: FlexDirection.Row }) {
  Image($r('app.media.heard'))
    .width(30)
    .borderRadius(15)
  Text() {
    Span('文本')
      .fontSize(15)
    ImageSpan($r('app.media.member'))
      .width('40px')
      .height('40px')
      .objectFit(ImageFit.Fill)
      .verticalAlign(ImageSpanAlignment.BASELINE)
      .onClick(() => {
        console.log('测试输出')
      })
    Span('\n')
    Span('昨天 12:00')
      .fontSize(12)
      .fontColor('#ffcac8c8')
  }
  .margin({
    left: 10
  })

  Text('+关注')
    .fontSize('28px')
    .fontColor('#ff8200')
    .border({
      width: 1,
      color: '#ff8200',
      radius: 10,
      style: BorderStyle.Solid
    })
    .padding({
      left: 5,
      right: 5,
      top: 2,
      bottom: 2
    })
    .position({ x: 280, y: 2 })
}

方案二:基于RelativeContainer相对布局实现图文混排效果

使用此方案RelativeContainer子组件要用alignRules布局组件位置,布局时需指定容器id。参与相对布局的容器内组件必须设置id,不设置id的组件组件不显示,容器id固定为__container__。

如以下核心代码中子组件都设置id,父容器未设置id时,父容器默认id固定为__container__。

核心代码

// 相对布局
RelativeContainer() {
  Image($r('app.media.heard'))
    .width(30)
    .borderRadius(15)
    .id('Image')
      // 以容器作为锚点布局
    .alignRules({
      top: { anchor: '__container__', align: VerticalAlign.Top },
      left: { anchor: '__container__', align: HorizontalAlign.Start }
    })
  Text() {
    Span('文本')
      .fontSize(15)
    ImageSpan($r('app.media.member'))
      .width('40px')
      .height('40px')
      .objectFit(ImageFit.Fill)
      .verticalAlign(ImageSpanAlignment.BASELINE)
      .onClick(() => {
        console.log('测试输出')
      })
    Span('\n')
    Span('昨天 12:00')
      .fontSize(12)
      .fontColor('#ffcac8c8')
  }
  .id('Text1')
  // 以容器内子组件作为锚点进行布局
  .alignRules({
    top: { anchor: 'Image', align: VerticalAlign.Top },
    left: { anchor: 'Image', align: HorizontalAlign.End }
  })
  .margin({
    left: 10
  })

  Text('+关注')
    .fontSize('28px')
    .fontColor('#ff8200')
    .border({
      width: 1,
      color: '#ff8200',
      radius: 10,
      style: BorderStyle.Solid
    })
    .id('Text2')
      // 以容器内子组件作为锚点进行布局
    .alignRules({
      top: { anchor: 'Text1', align: VerticalAlign.Top },
      left: { anchor: 'Text1', align: HorizontalAlign.End },
    })
    .margin({
      left: 150
    })
    .padding({
      left: 5,
      right: 5,
      top: 2,
      bottom: 2
    })
}

方案三:基于线性布局实现图文混排效果

基于线性布局实现图文混排时,节点数量会比较多。

核心代码

Row() {
  Image($r('app.media.img1'))
    .width(30)
    .borderRadius(15)

  Column() {
    Row() {
      Text('文本')
        .fontSize(15)
      Image($r('app.media.vvip_1'))
        .width(30)
        .borderRadius(15)
        .margin({ left: 10 })
        .position({ x: 40, y: 2 })
    }

    Text('昨天 12:00')
      .fontSize(12)
      .fontColor('#ffcac8c8')
  }
  .margin({ left: 10, top: 2 })
  // 设置Column容器内子组件水平方向上布局
  .justifyContent(FlexAlign.Start)
  // 设置Column容器内子组件垂直方向上布局
  .alignItems(HorizontalAlign.Start)

  Text('+关注')
    .fontSize('28px')
    .fontColor('#ff8200')
    .border({
      width: 1,
      color: '#ff8200',
      radius: 10,
      style: BorderStyle.Solid
    })
    .padding({
      left: 5,
      right: 5,
      top: 2,
      bottom: 2
    })
    .position({ x: 280, y: 2 })
}
.width('100%')
.margin({ left: 10, top: 50 })

方案四:基于StyledString(属性字符串)实现图文混排效果

使用StyledString实现图文混排效果,首先得让Text组件与StyledString绑定,绑定后即可使用StyledString设置文本样式以及对文本进行增、删、改、查等操作。

StyledString是一个方便灵活应用文本样式的对象,Text组件可通过TextController中的setStyleString方法与属性字符串绑定。绑定之后即可通过StyledString对文本进行增、删、改、查等一系列操作,并且可以用StyledString设置文本样式。

注意:

  1. 组件样式和属性字符串样式冲突时,属性字符串优先级高,冲突样式以属性字符串设置样式为准。
  2. Text子组件样式与属性字符串样式冲突,以属性字符串为准。
  3. 属性字符串对象不支持@State修饰。

核心代码

import { image } from '@kit.ImageKit'
import { LengthMetrics, LengthMetricsUnit } from '@ohos.arkui.node';

@Component
export struct FourTh {
  // PixelMap图片
  imagePixelMap: image.PixelMap | undefined = undefined;
  // 属性字符串对象
  mutableStr: MutableStyledString = new MutableStyledString('');
  controller: TextController = new TextController();
  // 基于属性字符串设置文本样式
  fontStyle2: StyledStringValue = new TextStyle({
    fontColor: '#ffcac8c8',
    fontSize: LengthMetrics.vp(12)
  })

  async aboutToAppear() {
    // 获取图片资源并同步解析成PixelMap
    this.imagePixelMap = await this.getPixmapFromMedia($r('app.media.member'));
  }

  // 同步将资源解析成PixelMap
  private async getPixmapFromMedia(resource: Resource) {
    let unit8Array = await getContext(this)?.resourceManager?.getMediaContent({
      bundleName: resource.bundleName,
      moduleName: resource.moduleName,
      id: resource.id
    })
    let imageSource = image.createImageSource(unit8Array.buffer.slice(0, unit8Array.buffer.byteLength));
    let createPixelMap: image.PixelMap = await imageSource.createPixelMap({
      desiredPixelFormat: image.PixelMapFormat.RGBA_8888
    });
    await imageSource.release();
    return createPixelMap;
  }

  build() {
    NavDestination() {
      Row() {
        Image($r('app.media.heard'))
          .width(30)
          .borderRadius(15)
          .margin({
            right: 10,
            top: 5
          })
        // Text组件绑定controller
        Text(undefined, { controller: this.controller })
          .fontSize(15)
        Text('+关注')
          .fontSize('28px')
          .fontColor('#ff8200')
          .border({
            width: 1,
            color: '#ff8200',
            radius: 10,
            style: BorderStyle.Solid
          })
          .padding({
            left: 5,
            right: 5,
            top: 2,
            bottom: 2
          })
          .position({ x: 280, y: 2 })
      }
      .onAppear(() => {
        setTimeout(() => {
          if (this.imagePixelMap !== undefined) {
            // ImageAttachment: New图形对象并设置样式
            this.mutableStr = new MutableStyledString(new ImageAttachment({
              value: this.imagePixelMap,
              size: { width: '40px', height: '40px' },
              // layoutStyle: { borderRadius: LengthMetrics.vp(10) },
              verticalAlign: ImageSpanAlignment.BASELINE,
              objectFit: ImageFit.Fill
            }))
          }
          // insertString:在指定字符之前插入文本,此处即在图片之前添加文本
          this.mutableStr.insertString(0, '文本');
          // 在图片之后添加文本
          let str = new StyledString('\n昨天  12:00', [{
            start: 0,
            length: 10,
            styledKey: StyledStringKey.FONT,
            styledValue: this.fontStyle2
          }])
          // appendStyledString: 在末尾位置追加新的属性字符串
          this.mutableStr.appendStyledString(str);
          // 通过TextController中的setStyledString方法让属性字符串与Text组件绑定
          this.controller.setStyledString(this.mutableStr);
        }, 100)
      })
      .height(200)
      .margin({ left: 10, top: 50 })
      .width('100%')
      .alignItems(VerticalAlign.Top)
    }.title('方案4')
  }
}

最后

小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为资料太多,太杂,教授的人也多,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)文档用来跟着学习是非常有必要的。 

为了确保高效学习,建议规划清晰的学习路线

GitCode - 全球开发者的开源社区,开源代码托管平台 希望这一份鸿蒙学习文档能够给大家带来帮助~


 鸿蒙(HarmonyOS NEXT)最新学习路线

该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案

路线图适合人群:

IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术

2.学习视频+学习PDF文档

HarmonyOS Next 最新全套视频教程 (鸿蒙语法ArkTS、TypeScript、ArkUI教程……)

​​

 纯血版鸿蒙全套学习文档(面试、文档、全套视频等)

                   

​​​​鸿蒙APP开发必备

​​

总结

【纯血版鸿蒙全套最新学习文档】

总的来说,华为鸿蒙不再兼容安卓,对程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,才能在这个变革的时代中立于不败之地。 

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值