基于原生能力实现图文混排

FengTianYa
发布于 2024-8-1 16:48
浏览
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') 
  } 
}

分类
已于2024-8-1 16:48:27修改
收藏
回复
举报
回复
    相关推荐