HarmonyOS鸿蒙Next中视图组件的宽度问题,如何设置组件的宽度为包裹内容类似安卓中的wrap_content

HarmonyOS鸿蒙Next中视图组件的宽度问题,如何设置组件的宽度为包裹内容类似安卓中的wrap_content

代码 如下

想要 TopBar 中的宽度可以自动根据文本的长度自动设置,我只需要控制 线的padding 就可以了

但是运行起来每个item的宽度都是全屏,这个有大神知道怎么改么?

import { Logger } from '../../../utils/Logger';
import { NavigationTabItemBean } from '../bean/NavigationTabItemBean'

const Tag = 'NavigationTabView'

@ComponentV2
export struct NavigationTabView {
  /**
   * 当前相中的item下标
   */
  @Param curSelectIndex: number | Resource = 0
  /**
   * navTab数组
   */
  @Param topBarList: Array<NavigationTabItemBean> = []
  /**
   * 点击事件
   */
  @Event onClickTabBar: (bean: NavigationTabItemBean) => void = () => {
    Logger.d(Tag, 'onClickTabBar def')
  };
  /**
   * 布局高度
   */
  @Param @Once rootLayoutHeight: number | Resource = 0
  /**
   * 跟布局左侧内边距
   */
  @Param @Once rootPaddingStart: number | Resource = 0
  /**
   * 跟布局右侧内边距
   */
  @Param @Once rootPaddingEnd: number | Resource = 0
  /**
   * 跟布局上方内边距
   */
  @Param @Once rootPaddingTop: number | Resource = 0
  /**
   * 跟布局下方内边距
   */
  @Param @Once rootPaddingBottom: number | Resource = 0
  /**
   * 跟布局背景颜色
   */
  @Param @Once rootBackGroundColor: Resource | Color = $r('app.color.transparent')
  /**
   * 未选中文本颜色
   */
  @Param @Once textColor: Resource | Color = $r('app.color.color_999999')
  /**
   * 选中文本颜色
   */
  @Param @Once selectTextColor: Resource | Color = $r('app.color.color_151515')
  /**
   * 文本字号
   */
  @Param @Once textSize: number | Resource = 15
  /**
   * 是否选中
   */
  @Param @Once isSelected: boolean = false
  /**
   * 是否展示下方指示线
   */
  @Param @Once showBottomLine: boolean = false
  /**
   * 未选中时 下方指示线颜色
   */
  @Param @Once bottomLineColor: Resource | Color = $r('app.color.transparent')
  /**
   * 下方指示线高度
   */
  @Param @Once bottomLineHeight: number | Resource = 2
  /**
   * 下方指示线宽度
   */
  @Param @Once bottomLineWidth: number | Resource = 0
  /**
   * 选中时 下方指示线颜色
   */
  @Param @Once selectBottomLineColor: Resource | Color = $r('app.color.transparent')
  /**
   * 子布局 左侧的内边距
   */
  @Param @Once itemPaddingStart: number | Resource = 0
  /**
   * 子布局 右侧的内边距
   */
  @Param @Once itemPaddingEnd: number | Resource = 0
  /**
   * 子布局 上侧的内边距
   */
  @Param @Once itemPaddingTop: number | Resource = 0
  /**
   * 子布局 下侧的内边距
   */
  @Param @Once itemPaddingBottom: number | Resource = 0
/**
 * 视图滑动方向
 */
  @Param @Once scrollable: ScrollDirection = ScrollDirection.None

  build() {
    Scroll() {
      Row() {
        ForEach(this.topBarList, (bean: NavigationTabItemBean) => {
          this.TopBar(bean)
        })
      }
    }.scrollable(this.scrollable)
    .scrollBar(BarState.Off)
    .height((this.rootLayoutHeight == 0) ? "auto" : this.rootLayoutHeight)
    .width("100%")
    .backgroundColor(this.rootBackGroundColor)
    .padding({
      left: this.rootPaddingStart,
      top: this.rootPaddingTop,
      bottom: this.rootPaddingBottom,
      right: this.rootPaddingEnd
    })

  }

  @Builder
  TopBar(bean: NavigationTabItemBean) {

    RelativeContainer() {
      Text(bean.title)
        .fontSize(this.textSize)
        .textAlign(TextAlign.Center)
        .fontColor((this.curSelectIndex == bean.index) ? this.selectTextColor : this.textColor)
        .padding({
          left: this.itemPaddingStart,
          right: this.itemPaddingEnd,
          top: this.itemPaddingTop,
          bottom: this.itemPaddingBottom
        })
        .alignRules({
          left:{anchor:'__container__',align:HorizontalAlign.Start},
          right:{anchor:'__container__',align:HorizontalAlign.End},
          bottom:{anchor:'__container__',align:VerticalAlign.Bottom},
          top:{anchor:'__container__',align:VerticalAlign.Top}
        })


      Text().height(this.bottomLineHeight)
        .backgroundColor((this.curSelectIndex == bean.index) ? this.selectBottomLineColor : this.bottomLineColor)
        .alignRules({
          left:{anchor:'__container__',align:HorizontalAlign.Start},
          right:{anchor:'__container__',align:HorizontalAlign.End},
          bottom:{anchor:'__container__',align:VerticalAlign.Bottom}
        })

    }.layoutWeight((this.scrollable == ScrollDirection.None) ? 1 : 0)
    .width('auto')
    .onClick(() => {
      this.onClickTabBar(bean)
    })
  }
}

/**
 * 导航标题的bean
 */
export interface NavigationTabItemBean{
  index:number
  title:string
}

更多关于HarmonyOS鸿蒙Next中视图组件的宽度问题,如何设置组件的宽度为包裹内容类似安卓中的wrap_content的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

【背景知识】

RelativeContainer是一种相对布局容器,用于在复杂场景中对多个子组件进行灵活的对齐和排列。从API Version 11开始,在RelativeContainer组件中,将widthheight设置为"auto"表示自适应子组件。

【解决方案】

RelativeContainer支持宽高自适应子组件,将其设置为auto即可,限制是当width设置为auto时,如果水平方向上子组件以容器作为锚点,则auto不生效,垂直方向上同理。具体可参考RelativeContainer的规则说明

更多关于HarmonyOS鸿蒙Next中视图组件的宽度问题,如何设置组件的宽度为包裹内容类似安卓中的wrap_content的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


  1. 不能设置固定宽度,因为内容长度不固定
  2. 设置为auto 时 每个item的宽度为屏幕宽度(不了解这个是什么机制)
  3. 不设置宽度,和设置为auto时一样的表现
  4. 设置为 LayoutPolicy.matchParent 宽度也是全屏

以上 数据源是后台返回的,有可能很长也有可能就一两个字 能怎么能实现宽度为包裹内容呢?

在HarmonyOS Next中,使用ArkUI框架的组件可以通过width属性设置为"wrap_content"来包裹内容。例如:

Text("示例文本")
  .width("wrap_content")

对于自定义组件或容器组件,同样适用此属性。在Row/Column布局中,子组件默认就是包裹内容(width:“wrap_content”),无需特殊设置。若需强制包裹内容,明确设置该属性即可。

在HarmonyOS Next中,要实现类似安卓wrap_content的效果,可以通过以下方式调整:

  1. 对于TopBar组件,当前设置了width('auto')是正确的,但问题出在RelativeContainer内部的Text组件布局规则上。修改TopBar构建器中的Text组件对齐规则:
Text(bean.title)
  .fontSize(this.textSize)
  .textAlign(TextAlign.Center)
  .fontColor((this.curSelectIndex == bean.index) ? this.selectTextColor : this.textColor)
  .padding({
    left: this.itemPaddingStart,
    right: this.itemPaddingEnd,
    top: this.itemPaddingTop,
    bottom: this.itemPaddingBottom
  })
  .width('auto')  // 添加这行
  .alignRules({
    left: {anchor: '__container__', align: HorizontalAlign.Start},
    top: {anchor: '__container__', align: VerticalAlign.Top}
  })
  1. 对于下方的指示线,同样需要调整宽度规则:
Text().height(this.bottomLineHeight)
  .width('auto')  // 添加这行
  .backgroundColor((this.curSelectIndex == bean.index) ? this.selectBottomLineColor : this.bottomLineColor)
  .alignRules({
    left: {anchor: '__container__', align: HorizontalAlign.Start},
    bottom: {anchor: '__container__', align: VerticalAlign.Bottom}
  })

关键点:

  • 使用width('auto')让组件宽度自适应内容
  • 简化alignRules规则,不需要强制设置right对齐
  • 确保RelativeContainer本身也设置了width('auto')

这样修改后,每个TopBar项的宽度将根据文本内容自动调整,而不会撑满全屏。

回到顶部