【HarmonyOS 4.0】容器组件

1. 线性布局(Row/Column)

  1. 自适应拉伸:空白填充 Blank 组件可作为 Column 和 Row 容器的子组件,该组件不显示任何内容,并且会始终充满容器主轴方向上的剩余空间,达到自适应拉伸效果。
  2. 自适应缩放:layoutWeight 属性可用于 Column 和 Row 容器的子组件,其作用是配置子组件在主轴方向上的尺寸权重。配置该属性后,子组件沿主轴方向的尺寸设置(width或height)将失效,具体尺寸根据权重进行计算。

1.1. Column - 沿垂直方向布局容器

  1. 支持通用属性,如 alignItems,justifyContent,width,height,border 等。
  2. justifyContent() 设置子元素沿主轴方向的排列方式,参数类型为枚举类型 FlexAlign.
  3. alignItems() 设置子元素沿交叉轴方向的对齐方式,参数类型为枚举类型 HorizontalAlign.
  4. .backgroundBlurStyle(BlurStyle.Regular) 为当前组件提供一种在背景和内容之间的模糊能力。
Column({space: 5}){} // 创建一个column容器组件,设置子元素间的垂直间距为5,纵向布局元素垂直方向间距为5.
 .alignItems(HorizontalAlign.Start)
 .justifyContent(FlexAlign.Center) // 

1.2. Row - 沿水平方向布局容器

  1. 支持通用属性,如 alignItems,justifyContent,width,height,border 等。
  2. justifyContent() 设置子元素沿主轴方向的排列方式,参数类型为枚举类型 FlexAlign.
  3. alignItems() 设置子元素沿交叉轴方向的对齐方式,参数类型为枚举类型 VerticalAlign.
Row({space: 5}){} // 横向布局元素间距
 .alignItems(VerticalAlign.Center)
 .justifyContent(FlexAlign.Start)

2. 层叠布局(Stack)

  1. 将多个组件沿垂直于屏幕的方向堆叠在一起,类似于图层的叠加。
  2. 层叠布局可通过 Stack 容器组件实现,其子元素会按照其添加顺序依次叠加在一起,后添加的子元素位于先添加的子元素之上。
  3. 组件的参数类型为{ alignContent?: Alignment },alignContent 用于设置子组件的对齐方式,该属性可通过枚举类型 Alignment 进行设置。
  4. 子组件Z轴控制:Stack 容器的子组件的层级除了可按照添加顺序决定,还能通过 zIndex() 进行手动设置,zIndex 的值越大,层级越高。
  5. 子组件精确定位:Stack 容器的子组件可使用 position() 方法进行更精确的定位,该方法可设置子组件左上角相对于 Stack 容器左上角的偏移量。

3. 弹性布局(Flex)

  1. 以弹性方式布局子组件的容器组件。
  2. alignItems() 设置子元素在交叉轴方向的对齐方式,参数类型为枚举类型 ItemAlign
  3. alignContent() 设置多行子组件在交叉轴方向的排列方式,该属性的类型为枚举类型 FlexAlign。

3.1 子组件常用属性

  1. 交叉轴对齐:alignSelf() 方法可以单独设置子组件自己的交叉轴对齐方式,并且优先级高于Flex容器alignItems。参数类型同样也是枚举类型 ItemAlign,各枚举值的含义也完全相同。
  2. 自适应伸缩:子组件沿主轴方向的尺寸具有弹性。即子组件的大小能够随着Flex容器尺寸的变化而自动伸缩。相关属性有 flexShrink()、flexGrow()、flexBasis() 。
  3. flexShrink() 默认值1,当父容器空间不足时,子组件的压缩比例。
    在这里插入图片描述
  4. flexGrow() 默认值0,用于“瓜分”父组件的剩余空间。
    在这里插入图片描述
  5. flexBasis() 设置子组件在父容器主轴方向上的基准尺寸。如果设置了该值,则子项占用的空间为设置的值;如果没设置该属性,那子项的空间为width/height的值。

4. 网格布局(Grid/GridItem)

  1. Grid容器组件和子组件GridItem,用于构建网格布局。

4.1 Grid - 网格容器

  1. fr (fraction比例、分数) 的个数即网格布局的行或列数,fr 前面的数值大小,用于计算该行或列在网格布局宽度上的占比,最终决定该行或列的宽度。
  2. 行:rowsTemplate()
  3. 列:columnsTemplate()
Grid() {
  ForEach(DataModel.getFirstGridData(), (item: ItemDate) => {
    GridItem() {
      Column() {
        Image(item.img)
          .width($r('app.float.home_homeCell_size'))
          .height($r('app.float.home_homeCell_size'))

        Text(item.title)
          .fontSize($r('app.float.little_text_size'))
          .margin({ top: $r('app.float.home_homeCell_margin') })
      }
    }
  })
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.rowsTemplate('1fr 1fr')
.columnsGap($r('app.float.home_grid_columnsGap'))
.rowsGap($r('app.float.home_grid_rowGap'))

4.2 GridItem - 网格容器中单项内容容器

  1. GridItem 组件支持横跨几行或者几列。
  2. 可以使用 rowStart()、rowEnd()、columnStart() 和columnEnd() 方法设置 GridItem 组件所占的单元格。
  3. Grid 容器中的行号和列号均从0开始。
  4. 在这里插入图片描述
  5. 行列间距:rowsGap()、.columnsGap() 属性,可以控制行列间距。

5. 列表布局(List/ListItem/ListItemGroup)

  1. ListItem 展示列表具体item,必须配合 List容器组件 来使用。
  2. scroller 参数用于绑定列表滚动控制器Scroller,Scroller可以控制列表的滚动。
private scroller: Scroller = new Scroller()

build(){
 List({space: 10, scroller: this.scroller})
 Button()
  .onClick(() => {
    this.scroller.scrollEdge(Edge.Top)
  })
}
  1. listDirection() 方法可以设置列表的主轴方向,其参数类型为枚举类型 Axis
  2. alignListItem() 方法可以设置子组件在交叉轴方向的对齐方式,其参数类型为枚举类型 ListItemAlign
  3. divider() 属性可设置列表元素分割线样式。
  4. .scrollBar() 方法可以设置滚动条状态,该方法的参数类型为枚举类型 BarState。
  5. onReachEnd(() => {}) 事件:列表到底末尾位置时触发。
    List边缘效果为弹簧效果时,划动经过末尾位置时触发一次,回弹回末尾位置时再触发一次。

6. 导航布局(Tabs/TabContent)

6.1 Tabs - 页签容器

  1. 通过页签进行内容视图切换的容器组件,每个页签对应一个内容视图。
  2. 基本用法如下:在这里插入图片描述
  3. barPosition: BarPosition 设置Tabs的页签位置。默认值:BarPosition.Start.
  4. index: number 设置当前显示页签的索引。默认值:0.
  5. controller: TabsController 设置Tabs控制器。
  6. .vertical():用于设置导航栏是否垂直排列,参数为boolean类型,默认值:false。
  7. .barPosition():用于设置Tabs的页签位置,参数为枚举类型BarPosition,默认值:BarPosition.Start。
  8. .barMode():将页签设置为可滚动的,参数为枚举类型BarMode,默认值:BarMode.Fixed。

6.1.1 TabsController

  1. Tabs组件的控制器,用于控制Tabs组件进行页签切换。不支持一个TabsController控制多个Tabs组件。
  2. 导入对象
private tabsController: TabsController = new TabsController()
  1. changeIndex(value: number): void 控制Tabs切换到指定页签。
this.tabsController.changeIndex(this.currentTabIndex)

6.2. TabContent - 页签内容视图

  1. 仅在Tabs中使用,对应一个切换页签的内容视图。
  2. TabContent() 组件表示每个页签的内容。其属性 .tabBar() 表示其对应的页签。
  3. 默认的页签只有文字内容,可以通过@Builder自定义导航栏实现图文并有的复杂页签。
  4. 自定义页签的选中状态需要我们自己实现。
    4.1 定义一个@State状态变量 currentIndex 表示当前选中的索引。
    4.2 触发 Tabs 的 onChange((index) => {this.currentIndex = index}) 事件 or 调用控制器的 changeIndex() 事件。
    4.3 通过传入给定的页签下标0,1,2 与 currentIndex 做判断来实现选中的状态。

代码示例1

import { PracticePage } from './PracticePage'

@Entry
@Component
struct Index {
  @State currentTabIndex: number = 0
  private tabsController: TabsController = new TabsController()

  build() {
    Column() {
      Tabs({ index: this.currentTabIndex, controller: this.tabsController }) {
        TabContent() {
          PracticePage()
        }.tabBar(this.barBuilder(0, $r('app.media.normal_answer_icon'), $r('app.media.answer_icon'), '答题'))

        TabContent() {
          Text('圈子')
        }
        .tabBar(this.barBuilder(1, $r('app.media.normal_circleOfFriends_icon'), $r('app.media.circleOfFriends_icon'),
          '圈子'))

        TabContent() {
          Text('我的')
        }.tabBar(this.barBuilder(2, $r('app.media.normal_mine_icon'), $r('app.media.mine_icon'), '我的'))
      }.tabsStyle()

      // .onChange((index: number) => {
      //   this.currentTabIndex = index
      // })
    }
    .height('100%')
    .width('100%')
  }

  @Builder
  barBuilder(tabBarIndex: number, icon: Resource, iconSelected: Resource, title: string) {
    Column() {
      Image(this.currentTabIndex === tabBarIndex ? iconSelected : icon).width(25).height(25)
      Text(title).tabTitleStyle(this.currentTabIndex === tabBarIndex ? Color.Black : '#959595')
    }
    .onClick(() => {
      this.currentTabIndex = tabBarIndex
      this.tabsController.changeIndex(this.currentTabIndex)
    })
  }
}

@Extend(Tabs)
function tabsStyle() {
  .vertical(false).barPosition(BarPosition.End).barMode(BarMode.Fixed)
}

@Extend(Text)
function tabTitleStyle(color: ResourceColor) {
  .fontSize(10)
  .fontColor(color)
  .fontWeight(FontWeight.Medium)
  .margin({ bottom: 2 })
}

代码示例2

// 导入Tabs组件的对象控制器
private controller: TabsController = new TabsController()

@Builder
TabBuilder(index: number, normalImg: Resource, selectedImg: Resource, title: string) {
  Column() {
    Image(index === this.currentIndex ? selectedImg : normalImg)
      .width($r('app.float.mainPage_baseTab_size'))
      .height($r('app.float.mainPage_baseTab_size'))

    Text(title)
      .margin({
        top: $r('app.float.mainPage_baseTab_top')
      })
      .fontSize($r('app.float.main_Tab_fontSize'))
      .fontColor(index === this.currentIndex ? $r('app.color.minePage_selected') : $r('app.color.minePage_normal'))
  }
  .justifyContent(FlexAlign.Center)
  .width(CommonConstants.FULL_PARENT)
  .height($r('app.float.mainPage_barHeight'))
  .onClick((index: number) => {
    this.currentIndex = index
    this.controller.changeIndex(this.currentIndex)
  })
}
  
Tabs({
  barPosition: BarPosition.End,
  controller: this.controller
}) {
  TabContent() {
    Home()
  }
  .padding({
    left: $r('app.float.mainPage_padding'),
    right: $r('app.float.mainPage_padding')
  })
  .backgroundColor($r('app.color.minePage_backgroundColor'))
  .tabBar(this.TabBuilder(
    CommonConstants.HOME_TAB_INDEX,
    $r('app.media.normal_home_icon'),
    $r('app.media.home_icon'),
    CommonConstants.HOME_TITLE
  ))

7. Scroll - 可滚动的容器组件

  1. 可滑动的容器组件,当子组件的布局尺寸超过父组件的视口时,内容可以滑动。
  2. Scroll(scroller?: Scroller)

7.1 Scroller

  1. 可滑动容器组件的控制器,可以将此组件绑定至容器组件,然后通过它控制容器组件的滑动,目前支持绑定到 List、Scroll、ScrollBar上。

7.1.1 导入对象

private scroller: Scroller = new Scroller()

7.1.2 绑定至容器组件

List({ scroller: this.scroller }) {
  ForEach(this.postInfoList, (item: PostInfo) => {
    ListItem() {
      PostItem({ post: item })
    }
  })
}

7.1.3 scrollTo

  1. 滑动到指定位置。

7.1.4 scrollEdge

  1. 滑动到容器边缘。

7.1.5 scrollPage

  1. 滑动到下一页或者上一页。

7.1.6 currentOffset

  1. 返回当前的滑动偏移量。

7.1.7 scrollToIndex

  1. 滑动到指定Index。
Button({ type: ButtonType.Circle }) {
  Image($r('app.media.ic_ok3')).width(14).height(14)
}.width(40).height(40).backgroundColor(Color.White).opacity(.5)
.onClick(() => {
  this.scroller.scrollToIndex(0)
})

8. Swiper - 滑块视图容器

  1. 提供子组件滑动轮播显示的能力
// 导入Swiper组件的对象控制器
private swiperController: SwiperController = new SwiperController()

Swiper(this.swiperController) {
  ForEach(DataModel.getSwiperImages(), (item: Resource) => {
    Image(item)
      .width(CommonConstants.FULL_PARENT)
      .height($r('app.float.home_swiper_height'))
      .borderRadius($r('app.float.home_swiper_borderRadius'))
      .objectFit(ImageFit.Contain)
  })
}
.index(0) // 设置当前在容器中显示的子组件的索引值。默认值:0
.autoPlay(true) // 子组件是否自动播放.默认值:false
.interval(3000) // 使用自动播放时播放的时间间隔,单位为毫秒。默认值:3000
.indicator(false) // 是否启用导航点指示器。
.loop(true) // 是否开启循环。默认值:true
.duration(400) // 子组件切换的动画时长,单位为毫秒。默认值:400
.vertical(false) // 是否为纵向滑动。默认值:false
.itemSpace(0) // 设置子组件与子组件之间间隙.默认值:0
.displayCount(1) // 设置一页内元素显示个数。默认值:1
// 主轴方向上元素排列的模式,优先以displayCount设置的个数显示,displayCount未设置时本属性生效.默认值:SwiperDisplayMode.Stretch
.displayMode(SwiperDisplayMode.STRETCH) // Swiper滑动一页的宽度为Swiper组件自身的宽度。
.cachedCount(1) // 设置预加载子组件个数。默认值:1
.disableSwipe(false) // 禁用组件滑动切换功能。默认值:false
.curve(Curve.Linear) // 设置Swiper的动画曲线,默认为线性曲线
.effectMode(EdgeEffect.Spring) // 滑动效果
.margin({
  top: $r('app.float.home_swiper_margin')
})

9. Counter - 计数器组件

  1. 计数器组件,提供相应的增加或者减少的计数操作。
  2. 可以包含子组件。
@state count: number = 1

Counter() {
	Text(this.count.toString())
}
.onInc(() => this.count++)
.onDec(() => this.count--)

10. RelativeContainer

  1. 相对布局组件,用于复杂场景中元素对齐的布局。
  2. 子组件可以将容器或者其他子组件设为锚点
  3. 参与相对布局的容器内组件必须设置id,不设置id的组件不显示,容器id固定为__container__。
Row() {
	RelativeContainer() {
	  Row().width(100).height(100)
	    .backgroundColor("#FF3333")
	    .alignRules({
	      top: {anchor: "__container__", align: VerticalAlign.Top},
	      left: {anchor: "__container__", align: HorizontalAlign.Start}
	    })
	    .id("row1")
	
	  Row().width(100).height(100)
	    .backgroundColor("#FFCC00")
	    .alignRules({
	      top: {anchor: "__container__", align: VerticalAlign.Top},
	      right: {anchor: "__container__", align: HorizontalAlign.End}
	    })
	    .id("row2")
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值