鸿蒙常用容器组件介绍

鸿蒙常用容器组件介绍

  • 前言
  • 总结
  • 1. Row/Column
  • 2. flex
  • 3. Stack
  • 4. List
  • 5. RelativeContainer
  • 6. Grid
  • 7. Scroll
  • 8. Tabs
  • 9. WaterFlow
  • 参考资料

前言

  1. 本文不介绍Text,Image这种单独的视图控件,主要还是过一下在构成一个复杂页面时所需要的外层的容器组件。免得在实际开发的时候要构建外层组件时不知道要用什么比较好

  2. 本文虽然也会贴一些测试代码,但是参考还是以鸿蒙的API参考为主,最好在上手这些视图的同时,学习如何看API参考:
    打开DevEco Studio -> View(视图) -> Tool Windows(工具窗口) -> API reference(API参考) -> ArkTs组件 -> 容器组件
    如果你的DevEco没有该视图,更新一下版本。

  3. 代码测试方式:在DevEco中新建一个arkTs文件,将正文的代码丢进去,启动preview功能即可。
    UI的点击事件和滚动功能不能直接通过@preview的测试标签来测试,必须要通过被@Entry标签标记过的页面才能生效,为了方便再贴上一个简单的页面代码。

在这里插入代码片
@Entry
@Component
export struct UIText {
  build() {
    Column() {
      //把正文的某个组件贴进来即可
    }.width('100%').height('100%')

  }
}

总结

一图流总结(这里的Android对标只是方便刚上手的时候理解,实际上鸿蒙的声明式UI的逻辑和Android的命令式并不同):

容器名称容器说明对标的Android视图
Row/Conlumn最常用的横向/纵向组件,里面的元素按照约定好的顺序排列LinearLayout
Flex柔性组件,自带换行功能的Row/ColumnLinearLayout
部分对应GridLayout
List和ListItem列表组件,当需要重复的元素排列的时候使用这个部分对应RecyclerView
Stack堆栈式组件,后加入的元素会覆盖前面的元素
但是实测别的布局也有这个特点,所以适用该布局的场景还有待探索
FrameLayout?
RelativeContainer相对组件,里面的控件都是根据和其他控件的相对位置来进行摆放RelativeLayout
ConstaintLayout
Grid网格组件,里面的元素按照网格进行排列,可以横向也可以纵向GridLayout
Scroll滑动组件,需要让某个页面可以滚动的时候就用它ScrollView
Tab标签组件,通过点击不同的项目展示不同的页面TabLayout
WaterFlow瀑布流容器,用它可以很方便的实现
淘宝首页那种左右视图不一样高的列表视图
/

1. Row/Column

最常用的排列视图的容器组件,可以横向排列或者纵向排列。这个还真没有什么好说的,哪个UI语言都有

内部的控件设置position的时候,剩下其他的元素会对应的往前
而设置offset的时候则不会。

@Preview
@Component
export struct ColumnRowView {
  build() {
    Column({space:10}) {

      Row() {
        Text('文案A')
          .fontColor('#FFFFFF')
          .margin({top:'20vp', bottom:'20vp', left:'20vp', right:'20vp'})
        Text('文案B')
          .fontColor('#FFFFFF')
          .margin({top:'20vp', bottom:'20vp', left:'20vp', right:'20vp'})
          .position({x:'50%', y:'50%'}) //文案B设置了绝对位置
        Text('文案C') // 文案C就顺位到第二个
          .fontColor('#FFFFFF')
          .margin({top:'20vp', bottom:'20vp', left:'20vp', right:'20vp'})
      }.backgroundColor('#123456').width('90%').height('20%')

      Row() {
        Text('文案A')
          .fontColor('#FFFFFF')
          .margin({top:'20vp', bottom:'20vp', left:'20vp', right:'20vp'})
        Text('文案B')
          .fontColor('#FFFFFF')
          .margin({top:'20vp', bottom:'20vp', left:'20vp', right:'20vp'})
          .offset({x:'40%', y:'40%'}) //文案B设置了相对于自身原本位置的相对位置
        Text('文案C') // 文案C没有顺位
          .fontColor('#FFFFFF')
          .margin({top:'20vp', bottom:'20vp', left:'20vp', right:'20vp'})
      }.backgroundColor('#123456').width('90%').height('20%')

    }.width('100%').height('100%')
  }
}

2. flex

柔性组件,这个布局我们可以把他简单的理解成加强版的Column或者Row

  1. 这个布局就可以通过参数设置的方式将其设定成横向或者纵向,反向的排列也能做到
  2. 可以自带换行功能,当放不下的时候自动换到下一行或者下一列,该功能也可以不启用。

简单介绍一下主轴和交叉轴的概念:
当内部元素横向排列的时候,横轴(X轴)就是主轴,纵轴(Y轴)就是交叉轴
纵向排列的时候也是同理,Y轴是主轴,X轴就反过来变成交叉轴

@Preview
@Component
export struct MyFlexView {
  build() {
    Column({space:10}) {

      //flex可以看成是自带换行功能的row或者Column
      //主轴和交叉轴
      Flex({direction:FlexDirection.Row, // 排列方式,行或者列或者反向的行列
        wrap:FlexWrap.Wrap, // 单行还是多行排列
        alignItems:ItemAlign.Start}) { // 所有子组件在交叉轴上的对齐方式
        Text('文案1').fontColor(0xffffff)
          .width('100').height('50')
          .margin({top:'20vp', bottom:'20vp', left:'20vp', right:'20vp'})
          .backgroundColor(0x123456)
        Text('文案2').fontColor(0xffffff)
          .width('100').height('100') // 没有办法通过flex实现瀑布流的那种左右自适应高度的效果
          .margin({top:'20vp', bottom:'20vp', left:'20vp', right:'20vp'})
          .backgroundColor(0x123456)
        Text('文案3').fontColor(0xffffff)
          .width('100').height('50')
          .margin({top:'20vp', bottom:'20vp', left:'20vp', right:'20vp'})
          .backgroundColor(0x123456)
      }.width('90%').height('100%').backgroundColor(0xFFCC99).align(Alignment.Center)


    }.height('100%').width('100%')
  }
}

3. Stack

堆栈组件,里面的元素都是直接摆放,后面放上去的视图在视觉效果上会显示在前面。

@Preview
@Component
export struct MyStackView {
  build() {
    Column({space:10}) {

      //后面一个视图会盖住前面视图的Stack
      Stack() {
        Text('我是第一加进来的视图').fontColor(0xffffff).backgroundColor(0x123456)
          .height('100%').width('100%')

        Text('我是第二个加进来的视图').width('100%').fontColor(0xffffff).backgroundColor(0xffcc99)
          .height('40%').width('50%').align(Alignment.Center)
      }.alignContent(Alignment.Bottom)

    }.width('100%').height('50%')
  }
}

4. List

列表组件,适用于摆放多个类型相同的视图

5. RelativeContainer

相对组件,里面的子组件的具体位置都是相对于其他的子组件来摆放的,需要做一个复杂UI的时候一般都把他丢在最外层。

@Preview
@Component
export struct MyRelativeView {
  build() {
    RelativeContainer() {

      //RelativeContainer的子组件必须得是有id这个方法的的容器
      Row()
        .backgroundColor(0xffcc99)
        .height('20%')
        .width('20%')
        .alignRules({
          top: { anchor: "__container__", align: VerticalAlign.Top },
          left: { anchor: "__container__", align: HorizontalAlign.Center }
        })
        .id('row1')

      // 和Stack一样,后面添加的View会覆盖前面的View
      Row()
        .backgroundColor(0x000000)
        .height('10%')
        .width('20%')
        .alignRules({
          top: { anchor: "__container__", align: VerticalAlign.Top },
          left: { anchor: "__container__", align: HorizontalAlign.Center }
        })
        .id('row2')

      // 虽然限制了10%的宽度,但是在设置了left和right且比10%更长的情况下会被拉长
      Row()
        .backgroundColor(0xf12562)
        .height('10%')
        .width('10%')
        .alignRules({
          top: { anchor: "row1", align: VerticalAlign.Bottom },
          left: { anchor: "__container__", align: HorizontalAlign.Start },
          right: { anchor: "row1", align: HorizontalAlign.Center },
        })
        .id('row3')

      // 在和第三个Row对齐的时候,仍然以其实际的宽高为准,而不是代码的10%
      Row() {
        Text('第4个Row')
      }.backgroundColor(0x999999)
      .height('10%')
      .width('20%')
      .alignRules({
        top: { anchor: "row3", align: VerticalAlign.Bottom },
        left: { anchor: "__container__", align: HorizontalAlign.Start },
        right: { anchor: "row3", align: HorizontalAlign.End },
      }).id('row4')

      // 如果约定好上下左右,不需要宽高也能设置视图
      Row() {
        Text('第5个Row')
      }.backgroundColor(0x777777)
      .alignRules({
        top: { anchor: "row1", align: VerticalAlign.Bottom },
        left: { anchor: "row1", align: HorizontalAlign.End },
        right: { anchor: "__container__", align: HorizontalAlign.End },
        bottom: { anchor: "row3", align: VerticalAlign.Bottom }
      }).id('row5')

    }.height('100%').width('100%')
  }
}

6. Grid

网格组件,当需要子组件以一定规则排列的时候就用它。
比较值得说的一个是rowsTemplate和columnsTemplate
以columnsTemplate来说明的话,你可以用这个方法,来指定grid存在多少列,每一行的比重是多少
比如columnsTemplate('1fr 2fr ')就是分为两列,第二列的宽度是三分二,第一列则是三分一
columnsTemplate('1fr 2fr 1fr ')就是分为三列,第二列的宽度是一半,第一列和第三列则是四分一


@Preview
@Component
export struct MyGridView {
  build() {

    Grid() {

      GridItem() {
        Text('1').fontColor(0xffffff)
      }
      .width('30%')
      .height('20%')
      .backgroundColor(0x111111)

      GridItem() {
        Text('2').fontColor(0xffffff)
      }
      .width('30%')
      .height('10%')
      .backgroundColor(0x111111)

      // 当判断放不下的时候就会自动换行
      GridItem() {
        Text('3').fontColor(0xffffff)
      }
      .width('30%')
      .height('20%')
      .backgroundColor(0x111111)

      GridItem() {
        Text('4').fontColor(0xffffff)
      }
      .width('30%')
      .height('20%')
      .backgroundColor(0x111111)

    }.width('100%').height('50%')
    .rowsGap(10) // 不同行之间的间距
    .columnsGap(25) // 不同列之间的间距
    //.columnsTemplate('1fr 2fr ') // 将GridItem分为两列,第二列的高度分了2/3,第一列分了1/3
    .rowsTemplate('1fr 2fr 1fr') // 将Grid分为两行,同时设置rowsTemplate和columnsTemplate时会出问题,所以分开调试
    // 当用上rowsTemplate或columnsTemplate的时候,item自己的宽高功能的设置就会某种程度的失效,需要多用preview确认

  }
}

7. Scroll

滑动组件,当内部子组件的高度或者宽度超出可以父组件可以显示的距离时,可以通过滑动的方式查看内容

  1. 原本它有个既可以横向又可以纵向滑动的free模式,但是API9开始就废弃了,所以目前单个的Scroll组件只能横向或纵向滑动。
@Preview
@Component
export struct MyScroll {
  build() {

    Column() {
      Scroll() {
        // 滑动组件只能有一个子组件,通过该子组件来摆放实际的UI
        Row() {
          Text('1').height('10%').width('50%').backgroundColor(0x999999)
          Text('2').height('10%').width('50%').backgroundColor(0x999999)
          Text('3').height('10%').width('50%').backgroundColor(0x999999)
        }
      }.height('50%').width('100%').scrollable(ScrollDirection.Horizontal)

      Scroll() {
        Column() {
          Text('1').height('50%').width('50%').backgroundColor(0x999999)
          Text('2').height('50%').width('50%').backgroundColor(0x999999)
          Text('3').height('50%').width('50%').backgroundColor(0x999999)
        }
      }.height('50%').width('100%').scrollable(ScrollDirection.Vertical)

    }
  }
}

8. Tabs

标签组件,有不同的标签视图和内容视图,点击不同的标签就会切换到对应的内容视图。

Tabs由三个不同的部分组成
tabBar:标签,用于标明不同视图的标签,是一个自定义UI,案例代码写的就是普通的Button
tabContent:内容,用于展示不同的内容,也是一个自定义UI,案例代码写的是普通的Text
TabsController:tabs的控制类,用于处理不同tab之间的切换逻辑。

@Preview
@Component
export struct MyTabView {

  private tabsController = new TabsController() // 用于控制tabs切换到不同的tab

  @Builder
  myTabBar(pos: number) {
    // 修改这里的高度过高了会失效,需要在tabs里面修改
    Button('tabBar' + pos).backgroundColor(0x888888).height(50)//.height(300)
      .onClick(() => {
        this.tabsController.changeIndex(pos-1) // 点击不同的tabBar就会切换到对应的tabContent
      })
  }

  @Builder
  myTabContent(pos: number) {
    Text('tabContent' + pos).backgroundColor(0x999999).height(100)
      .onClick(() => {
        console.log(pos + "")
      })
  }


  build() {
    Tabs({
      barPosition: BarPosition.Start,  //
      controller: this.tabsController }) {

      TabContent() {
        this.myTabContent(1)
      }.tabBar(this.myTabBar(1))

      TabContent() {
        this.myTabContent(2)
      }.tabBar(this.myTabBar(2))

      TabContent() {
        this.myTabContent(3)
      }.tabBar(this.myTabBar(3))

    }.height('100%').width('100%')
    .barHeight(100).barBackgroundColor(0x777777) // tabBar的高度由tabs控制
  }
}

9. WaterFlow

瀑布流组件,他在grid的基础上,支持每个视图大小都不一样的情况时,仍然可以正常排列
在这里插入图片描述


@Component
export struct MyFlowView {
  build() {
    WaterFlow() {

      FlowItem() {
        Text('item1').height('50%').width('50%').backgroundColor(0x888888)
      }

      FlowItem() {
        Text('item2').height('60%').width('50%').backgroundColor(0x777777)
      }

      FlowItem() {
        Text('item3').height('30%').width('50%').backgroundColor(0x888888)
      }

      FlowItem() {
        Text('item4').height('40%').width('50%').backgroundColor(0x999999)
      }

      // 这两个加起来都没有超过右边的高度,所以一起在左边
      FlowItem() {
        Text('item5').height('10%').width('50%').backgroundColor(0x999999)
      }
      FlowItem() {
        Text('item6').height('10%').width('50%').backgroundColor(0x999999)
      }

    }.height('100%').width('100%')
    .columnsTemplate('1fr 1fr').columnsGap(10) // 通过columnsTemplate来限制有多少列,每列占多少比重
    .rowsGap(10)
    //.rowsTemplate('1fr 1fr 1fr')
  }
}

参考资料

  1. 鸿蒙API参考
  2. harmony 鸿蒙弹性布局(Flex)
    https://www.seaxiang.com/blog/022dc7507623403d8b5ee6af7f382dd8#menu_7

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/338264.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Unity学习笔记】New Input System 部分源码和测试用例补充

转载请注明出处:🔗https://blog.csdn.net/weixin_44013533/article/details/135630016 作者:CSDN|Ringleader| 主要参考: Unity官方Input System手册与API【Unity学习笔记】Unity TestRunner使用【Unity学习笔记】第十二 New Inp…

【征服redis14】认真理解一致性Hash与Redis的三种集群

前面我们介绍了主从复制的方式和sentinel方式,这里我们看第三种模式-Cluster方式。 目录 1.前两种集群模式的特征与不足 2.Cluster模式 2.1 Cluster模式原理 2.2 数据分片与槽位 2.3 Cluster模式配置和实现 3.一致性Hash 3.1 哈希后取模 3.2 一致性Hash算法…

proteus8.15安装教程

proteus8.15安装教程 1.管理员运行 2.一直NEXT到这一步,需要注意,一定要选这一个 3.选中后出现 4.一直下一步到更新 这边结束后准备激活: 1.安装激活插件,先关闭防火墙 2.下一步 3.最后,将数据库放在根目录下 …

RHEL - 更新升级软件或系统

《OpenShift / RHEL / DevSecOps 汇总目录》 文章目录 小版本软件更新yum update 和 yum upgrade 的区别升级软件和升级系统检查软件包是否可升级指定升级软件使用的发行版本方法1方法2方法3方法4 查看软件升级类型更新升级指定的 RHSA/RHBA/RHEA更新升级指定的 CVE更新升级指定…

【C语言】深度探讨文件操作(一)

文章目录 📝前言🌠 为什么使用文件?🌉什么是文件? 🌠程序文件🌉数据文件 🌠文件名🌉二进制文件和文本文件? 🌠文件的打开和关闭🌉 流和…

机器人电机综述 — 电机分类、舵机、步进与伺服、物理性质和伺服控制系统

电机综述 图片与部分素材来自知乎大佬不看后悔!最全的电机分类,看这一篇就够了! - 知乎 (zhihu.com),本文只是把机器人中常用的电机知识提炼了一下 1 按照结构和工作原理划分 1. 同步电机 ​ 电机的转速与定子磁场的转速相同步…

《WebKit 技术内幕》之八(1):硬件加速机制

《WebKit 技术内幕》之八(1):硬件加速机制 1 硬件加速基础 1.1 概念 这里说的硬件加速技术是指使用GPU的硬件能力来帮助渲染网页,因为GPU的作用主要是用来绘制3D图形并且性能特别好,这是它的专长所在,它…

k8s 使用cert-manager证书管理自签

个人建议使用安装更快,比helm快,还要等待安装crd kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.yaml#官网 https://cert-manager.io/docs/installation/kubectl/#创建自签的ClusterIssuer c…

数据库设计最佳实践:学院个人信息管理系统中的MySQL优化

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

【C++记忆站】类和对象(一)

类和对象(一) 1.面向过程和面向对象初步认识 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题 C是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间…

2024年热门项目管理软件推荐:提升项目管理效率的工具集合

项目管理系统软件有哪些?本文将根据项目管理系统软件的功能、选择项目管理系统软件对公司的好处,根据国际上知名软件评测网站G2 Grid的评测结果对8款2024年好用的项目管理软件:Zoho Projects、Smartsheet、monday、Asana、ClickUp、Notion、A…

elasticsearch备份恢复,elasticdump使用

准备环境 1. 将node-v10.23.1-linux-x64.tar.xz上传到服务器/usr/local目录下 2. tar xf node-v10.23.1-linux-x64.tar.xz 3. 将node_modules.tar.gz上传到服务器/usr/local目录 4. tar -zxvf node_modules.tar.gz 5. 设置NODE环境 5.1 vim /etc/profile export NODEJS_…

YOLOv5全网首发:新一代高效可形变卷积DCNv4如何做二次创新?高效结合SPPF

💡💡💡本文独家改进:DCNv4更快收敛、更高速度、更高性能,与YOLOv5 SPPF高效结合 收录 YOLOv5原创自研 https://blog.csdn.net/m0_63774211/category_12511931.html 💡💡💡全网独家首发创新(原创),适合paper !!! 💡💡💡 2024年计算机视觉顶会创…

[python]使用pyqt5搭建yolov8钢筋计数一次性钢材计数系统

【官方框架地址】 github地址:https://github.com/ultralytics/ultralytics 【算法介绍】 Yolov8是一种先进的深度学习模型,用于目标检测和识别。在钢筋计数任务中,Yolov8可以有效地识别和计数图像中的钢筋。下面是对如何使用Yolov8实现钢筋…

Java SE入门及基础(25)

目录 方法带参(续第24篇) 6.方法参数传递规则 方法传参来自官方的说明 基本数据类型传值案例 基本数据类型传值时传递的是值的拷贝 引用数据类型传值案例 引用数据类型传值时传递的是对象在堆内存上的空间地址 Java SE文章参考:Java SE入门及基础知…

【C++第二课 - 类和对象上 - 入门知识】struct类、class类、访问限定符、this指针

目录 面向过程与面向对象初步认识类的定义struct定义类class定义类 类的访问限定符及封装访问限定符 声明与定义分离this指针类成员的命名问题this 类的实例化类的对象大小的计算成员函数为何不在对象里面类对象大小计算 面向过程与面向对象初步认识 C语言是面向过程的&#x…

线程和进程的区别(从JVM角度出发)

进程与线程的区别 线程具有许多传统进程所具有的特征,故又称为轻型进程(Light—Weight Process)或进程元;而把传统的进程称为重型进程(Heavy—Weight Process),它相当于只有一个线程的任务。在引入了线程的操作系统中,通常一个进…

Linux 的提示符太长了,帮你精简一下

普通用户修改文件 ~/.bashrc 修改 50 行左右的代码,将两个w改为大写的W 如果是root用户则修改文件/root/.bashrc,同样的方法。

自然语言推断:注意力之注意(Attending)

注意(Attending) 第一步是将一个文本序列中的词元与另一个序列中的每个词元对齐。假设前提是“我确实需要睡眠”,假设是“我累了”。由于语义上的相似性,我们不妨将假设中的“我”与前提中的“我”对齐,将假设中的“累…

数据结构——循环链表

1.循环单链表 最后一个结点的指针不是NULL,而是指向头结点 单链表和循环单链表的比较: 单链表:从一个结点出发只能找到该结点后续的各个结点;对链表的操作大多都在头部或者尾部;设立 头指针,从头结点找到尾部的时间…