序言:
本文详细介绍了弹性布局、绝对定位、层叠布局等布局知识并给出相应的具体案例和实现代码,目录第六节【界面开发实战-支付宝界面】整合前三期笔记的所有内容,实现了真正意义上我们平时所看见的App应用中使用的界面效果,并添加了Scoll滚动界面的用法。
笔者也是跟着B站黑马的课程一步步学习,学习的过程中添加部分自己的想法整理为笔记分享出来,如有代码错误或笔误,欢迎指正。
B站黑马的课程链接:鸿蒙课程介绍_哔哩哔哩_bilibili
往期笔记:
【01】纯血鸿蒙HarmonyOS NEXT星河版开发0基础学习笔记-ArkTs基础语法与界面开发基础-CSDN博客
【02】纯血鸿蒙HarmonyOS NEXT星河版开发0基础学习笔记-界面进阶与布局排布(附QQ登陆、得物、京东登陆综合案例+代码)-CSDN博客
目录
一.弹性布局(Flex)
弹性容器组件:Flex()
1.基本使用:
Flex(){
子组件1
子组件2
子组件3
子组件N
}
①主轴方向:direction
②主轴对齐方式:justifyContent
③交叉轴对齐方式:alignItems
④布局换行:wrap
例子:添加direction:FlexDirection.Column后
例子:添加justifyContent:FlexAlign.Center后
例子:添加alignItems:ItemAlign.Center并把justifyContent:FlexAlign改为SpaceAroun
代码:
build() {
//flex默认主轴水平往右,交叉轴垂直往下->类似Row
//1.主轴方向
Flex({direction:FlexDirection.Column,
justifyContent:FlexAlign.SpaceAround,
alignItems:ItemAlign.Center}){
Text()
.width(80) .height(80)
.backgroundColor(Color.Orange)
.border({width:2,color:Color.Blue})
Text()
.width(80) .height(80)
.backgroundColor(Color.Orange)
.border({width:2,color:Color.Blue})
Text()
.width(80) .height(80)
.backgroundColor(Color.Orange)
.border({width:2,color:Color.Blue})
}
.width('100%') .height(600)
.backgroundColor('#5f9a5c')
}
tip:单行或单列的情况,优先还是使用线性布局(本质是基于Flex设计的,并且还做了性能优化),但涉及到布局换行的情况往往需要使用flex。
2.warp属性:Flex是单行布局还是多行布局
①FlexWrap.NoWrap 单行布局
②FlexWrap.Wrap 多行布局
如果一行有五个方块盒子,就会出现拉伸或压缩的情况,这种时候就可以利用Flex()的wrap进行灵活的调整。
这个只用记Flex.Wrap和Flex.NoWrap即可,其他的不常用且反人类。
3.小案例-阶段选择
代码:
build() {
Column(){
Text('阶段选择')
.fontSize(30)
.fontWeight(700)
.padding(15)
Flex({wrap:FlexWrap.Wrap}){
Text('ArkUI')
.padding(15)
.margin(5)
.backgroundColor('#F1F1F1')
Text('ArkTs')
.padding(15)
.margin(5)
.backgroundColor('#F1F1F1')
Text('界面开发')
.padding(15)
.margin(5)
.backgroundColor('#F1F1F1')
Text('系统能力')
.padding(15)
.margin(5)
.backgroundColor('#F1F1F1')
Text('权限控制')
.padding(15)
.margin(5)
.backgroundColor('#F1F1F1')
Text('河马繁殖')
.padding(15)
.margin(5)
.backgroundColor('#F1F1F1')
}
}
}
二.绝对定位-Position
作用:控制组件位置,可以实现层叠效果。
特点:
①参照 父组件左上角 进行偏移
②绝对定位后的组件 不再占用自身原有位置
语法: .position(位置对象)
参数:{x:水平偏移量,y:垂直偏移量}
绝对定位是一种非常方便的可以控制组件位置的语法
可以通过调整xy位置灵活的让关羽跑来跑去,并且不再占据原有位置,实现重叠效果
代码:
build() {
Column(){
Text('刘备')
.width(80) .height(80)
.backgroundColor(Color.Orange)
Text('关羽-定位')
.width(80) .height(80)
.backgroundColor(Color.Green)
.position({x:0,y:0})
Text('张飞')
.width(80) .height(80)
.backgroundColor(Color.Red)
}
.width(300) .height(300)
.backgroundColor(Color.Pink)
}
tip:后面的组件明显层次更高(张飞盖住关羽,关羽盖住刘备),会覆盖前面的组件
需求:在不动结构的情况下,调整组件的层级,可以通过.zIndex,如如果想要刘备盖住张飞关羽,可以添加.zIndex(3)即可实现。
三.综合案例-卡片《人气热播故事》
1.思路分析:
①整体:从上往下布局 Column
②局部:先图片、再Row(图 + 文本)
③细节:VIP(定位、圆角)
2.代码:
build() {
Column(){
//思路:先整体,再局部,再细节
Column(){
//定位的vip不会影响到其他子元素的展示
Text('VIP')
.width(40) .height(20)
.backgroundColor(Color.Orange)
.borderRadius({topLeft:10,bottomRight:10})
.borderColor(Color.White)
.border({width:2,color:'#fbe7a3'})
.fontColor('#fbe7a3')
.fontSize(14)
.fontWeight(700)
.fontStyle(FontStyle.Italic)
.position({x:0,y:0})
.zIndex(666)
.padding({left:5})
//上图
Image($r('app.media.position_moco'))
.width('100%') .height(210)
.borderRadius({topLeft:10,bottomLeft:20,bottomRight:20})
//下Row()文本
Row(){
Image($r('app.media.position_earphone'))
.width(20)
.backgroundColor('#55b7f4')
.borderRadius(10)
.fillColor(Color.White)
.padding(2)
Text('飞狗MOCO')
.padding({left:10})
.fontWeight(700)
}
.padding(5)
}
.width(160) .height(240)
.backgroundColor(Color.White)
}
.width('100%') .height('100%')
.backgroundColor(Color.Pink)
}
四.层叠布局
层叠布局具有较强的组件层叠能力。
场景:卡片层叠效果等
特点:层叠操作更简洁,编码效率高(绝对定位的优势是更加灵活)
Stack容器内的子元素的顺序为Item1→Item2→Item3
九种位置的不同语法:
//例:Stack({alignContent:Alignment.Center}){...}
代码:
build() {
Stack({alignContent:Alignment.Center}){
Text()
.width(300) .height(300)
.backgroundColor(Color.Black)
Text()
.width(200) .height(200)
.backgroundColor(Color.Blue)
Text()
.width(100) .height(100)
.backgroundColor(Color.Pink)
}
.width('100%')
}
五.综合案例-B站视频卡片
1.思路分析:
①整体:Column纵向布局
②区域划分:
Ⅰ.上面图片区域(层叠布局)
图片组件 + 文本修饰(播放、评论、时长)
Ⅱ.下面文字区域(上下结构)
标题文字 + 点赞说明 (点赞量、更多)
代码:
build() {
Column(){
Column() {
//图片区域
Stack({ alignContent: Alignment.Bottom }) {
//主图
Image($r('app.media.bz_img'))
.borderRadius({ topLeft: 10, topRight: 10 })
//播放量一行
Row() {
Row({space:5}) {
Image($r('app.media.bz_play'))
.width(14)
.fillColor(Color.White)
Text('288万')
.fontSize(12)
.fontColor(Color.White)
}
.padding({left:5})
.margin({right:5})
Row({space:5}) {
Image($r('app.media.bz_msg'))
.width(14)
.fillColor(Color.White)
Text('8655')
.fontSize(12)
.fontColor(Color.White)
}
Blank() //占格函数
Text('4:33')
.fontSize(12)
.fontColor(Color.White)
.padding({right:10})
}
.width('100%') .height(24)
}
.width('100%') .height(125)
Column(){
Text('【凤凰传奇新歌】 欢迎来到国风统治区:唢呐一响神曲《铁衣流派推广曲》')
.fontSize(13)
.textOverflow({overflow:TextOverflow.Ellipsis})
.maxLines(2)
.padding({top:3,left:3,right:3})
}
Blank()
Row(){
Text('19万点赞')
.fontSize(12)
.fontColor('#e66c43')
.backgroundColor('#fef0ef')
.padding(5)
.borderRadius(5)
Image($r('app.media.bz_more'))
.width(14)
}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.padding({left:8,bottom:5,right:5})
}
.width(200) .height(200)
.backgroundColor(Color.White)
.borderRadius(10)
.margin({top:10})
}
.width('100%') .height('100%')
.backgroundColor('#ccc')
}
六.界面开发实战-支付宝界面
1.思路分析:
阶段1:底部导航
build() {
//1.整体的Stack布局+底部的tab
//2.主体区域的架子:头部+主体页面(可滚动)
//Column/Row 默认不具备可滚动的效果-》Scroll
Stack({alignContent:Alignment.Bottom}){
//主体展示区
Stack({alignContent:Alignment.Top}){
//头部
Row(){
Text('搜索区域')
}
.zIndex(888)
.width('100%') .height(60)
.backgroundColor('#5b73de')
//主体页面
Scroll(){
Column(){
Text('测试文本').height(200)
Text('测试文本').height(200)
Text('测试文本').height(200)
Text('测试文本').height(200)
Text('测试文本').height(200)
Text('测试文本').height(200)
Text('测试文本').height(200)
}
.width('100%')
}
}
.width('100%') .height('100%')
//底部Tab导航区
Row(){
Column(){
Image($r('app.media.zfb_tab_home'))
.width(35)
}
.layoutWeight(1)
Column(){
Image($r('app.media.zfb_tab_money'))
.width(28)
Text('理财')
.padding({top:1})
.fontSize(13)
}
.layoutWeight(1)
Column(){
Image($r('app.media.zfb_tab_life'))
.width(28)
Text('生活')
.padding({top:1})
.fontSize(13)
}
.layoutWeight(1)
Column(){
Image($r('app.media.zfb_tab_chat'))
.width(28)
Text('消息')
.padding({top:1})
.fontSize(13)
}
.layoutWeight(1)
Column(){
Image($r('app.media.zfb_tab_me'))
.width(28)
Text('我的')
.padding({top:1})
.fontSize(13)
}
.layoutWeight(1)
}
.width('100%') .height(60)
.backgroundColor('#fbfcfe')
}
.width('100%').height('100%')
.backgroundColor(Color.Pink)
}
阶段2:顶部
阶段3:顶部快捷按钮
阶段4:导航模块
阶段5:最终成品
代码:
build() {
//1.整体的Stack布局+底部的tab
//2.主体区域的架子:头部+主体页面(可滚动)
//Column/Row 默认不具备可滚动的效果-》Scroll
Stack({alignContent:Alignment.Bottom}){
//主体展示区
Stack({alignContent:Alignment.Top}){
//头部
Row(){
//左
Column(){
Text('北京')
.fontColor('#fff') .fontSize(18)
Text('晴 2℃')
.padding({top:3})
.fontColor('#fff') .fontSize(13)
Image($r('app.media.zfb_head_down'))
.fillColor('#fff')
.width(14)
.position({x:40,y:0})
}
//中
Row(){
Image($r('app.media.zfb_head_search'))
.width(20)
.fillColor('#666')
.margin({left:5,right:5})
Text('北京交通一卡通')
.layoutWeight(1)
.fontSize(15) .fontColor('#666')
Text('搜索')
.width(55)
.fontColor('#5b73de') .fontWeight(700)
.textAlign(TextAlign.Center)
.border({width:{left:1},color:'#ccc'})
}
.height(32)
.layoutWeight(1)
.backgroundColor('#fff')
.borderRadius(5)
.margin({left:25})
//右
Row(){
Image($r('app.media.zfb_head_plus'))
.fillColor('#ccc')
.width(32)
}
.padding({left:10})
}
.padding({left:10,right:10})
.zIndex(888)
.width('100%') .height(60)
.backgroundColor('#5b73de')
//主体页面
Scroll(){
Column(){
//TOP快捷按钮区域
Row(){
Column(){
Image($r('app.media.zfb_top_scan'))
.width(36)
.fillColor('#fff')
Text('扫一扫')
.fontSize(14) .fontColor('#fff')
}
.layoutWeight(1)
Column(){
Image($r('app.media.zfb_top_pay'))
.width(36)
.fillColor('#fff')
Text('收付款')
.fontSize(14) .fontColor('#fff')
}
.layoutWeight(1)
Column(){
Image($r('app.media.zfb_top_travel'))
.width(36)
.fillColor('#fff')
Text('出行')
.fontSize(14) .fontColor('#fff')
}
.layoutWeight(1)
Column(){
Image($r('app.media.zfb_top_card'))
.width(36)
.fillColor('#fff')
Text('卡包')
.fontSize(14) .fontColor('#fff')
}
.layoutWeight(1)
}
.padding({top:5,bottom:15})
.backgroundColor('#5b73de')
//主体区(背景色#f6f6f6)
Column({space:10}){
//导航区
Column(){
Row(){
Column() {
Image($r('app.media.zfb_nav1'))
.width(28).margin({ bottom: 8 })
Text('滴滴出行')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav2'))
.width(28).margin({ bottom: 8 })
Text('生活缴费')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav3'))
.width(28).margin({ bottom: 8 })
Text('股票')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav4'))
.width(28).margin({ bottom: 8 })
Text('蚂蚁森林')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav5'))
.width(28).margin({ bottom: 8 })
Text('手机充值')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
}
.padding(5)
Row(){
Column() {
Image($r('app.media.zfb_nav6'))
.width(28).margin({ bottom: 8 })
Text('余额宝')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav7'))
.width(28).margin({ bottom: 8 })
Text('花呗')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav8'))
.width(28).margin({ bottom: 8 })
Text('飞猪旅行')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav9'))
.width(28).margin({ bottom: 8 })
Text('淘票票')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav10'))
.width(28).margin({ bottom: 8 })
Text('饿了么')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
}
.padding(5)
Row(){
Column() {
Image($r('app.media.zfb_nav11'))
.width(28).margin({ bottom: 8 })
Text('读书听书')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav12'))
.width(28).margin({ bottom: 8 })
Text('基金')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav13'))
.width(28).margin({ bottom: 8 })
Text('直播广场')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav14'))
.width(28).margin({ bottom: 8 })
Text('医疗健康')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
Column() {
Image($r('app.media.zfb_nav15_more'))
.width(28).margin({ bottom: 8 })
Text('更多')
.fontColor('#666').fontSize(12)
}
.layoutWeight(1)
}
.padding(5)
}
.padding({top:5})
//产品区
Row({space:5}){
Image($r('app.media.zfb_pro_pic1'))
.layoutWeight(1)
Image($r('app.media.zfb_pro_pic2'))
.layoutWeight(1)
Image($r('app.media.zfb_pro_pic3'))
.layoutWeight(1)
}
.padding(10)
Column(){
Image($r('app.media.zfb_pro_list1'))
.width('100%')
Image($r('app.media.zfb_pro_list2'))
.width('100%')
}
.padding(10)
}
.width('100%')
.backgroundColor('#f6f6f6')
.borderRadius({
topLeft:15,topRight:15
})
}
.width('100%')
.padding({top:60,bottom:60})//防止被头部和底部的导航tab盖住导致丢失信息
}
}
.width('100%') .height('100%')
//底部Tab导航区
Row(){
Column(){
Image($r('app.media.zfb_tab_home'))
.width(35)
}
.layoutWeight(1)
Column(){
Image($r('app.media.zfb_tab_money'))
.width(28)
Text('理财')
.padding({top:1})
.fontSize(13)
}
.layoutWeight(1)
Column(){
Image($r('app.media.zfb_tab_life'))
.width(28)
Text('生活')
.padding({top:1})
.fontSize(13)
}
.layoutWeight(1)
Column(){
Image($r('app.media.zfb_tab_chat'))
.width(28)
Text('消息')
.padding({top:1})
.fontSize(13)
}
.layoutWeight(1)
Column(){
Image($r('app.media.zfb_tab_me'))
.width(28)
Text('我的')
.padding({top:1})
.fontSize(13)
}
.layoutWeight(1)
}
.width('100%') .height(60)
.backgroundColor('#fbfcfe')
}
.width('100%').height('100%')
.backgroundColor('#5b73de')
}
感谢观看。
ps:半夜睡不着觉,看黑马的支付宝设计图写案例,这个案例写了快两个小时-2024.9.6 1:30