本文正在参加华为鸿蒙有奖征文征文活动
版本环境
API版本:9
DevStudio版本:
DevEco Studio 4.1 Release
Build Version: 4.1.0.400, built on April 9, 2024
Build #DS-223.8617.56.36.410400
Runtime version: 17.0.6+10-b829.5 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
Windows 11 10.0
GC: G1 Young Generation, G1 Old Generation
Memory: 1536M
Cores: 16。
模拟器:Remote Emulator P50 api9 arm
吐吐:由于本电脑死活无法启动本地模拟器,so改用远程模拟器,可是远程模拟器如上图所示,经常没有资源可用,Unable to apply for a remote emulator: No device available. Please try again later.。。。
资料指南
相关资料和官网权限
- 官网首页:www.harmonyos.com/
- HarmonyOS代码仓库:gitee.com/openharmony
- API指南:developer.huawei.com/consumer/cn…
- 应用开发指南:developer.huawei.com/consumer/cn…
- DevStudio下载相关:developer.huawei.com/consumer/cn…
开发
作为应用首页场景,经常会有些创意实现,首页支撑这很多数据,常常是一个可滑动列表展示数据,头部固定搜索框方便用户直达想要的内容,使用一些动画处理可以吸晴用户。
应用布局:
Tabs切换实现应用界面框架
Tabs({barPosition:BarPosition.End,controller:this.mTabController}){
TabContent(){
HomeView()
}.tabBar(this.TabBuilder("首页",0,$r('app.media.macbook'),$r('app.media.one_normal')))
TabContent(){
SecondView()
}.tabBar(this.TabBuilder("种草",1,$r('app.media.book'),$r('app.media.two_normal')))
… })
首页布局代码:自定义头部View+ 可滑动列表List+LazyForEach懒加载数据
Column() {
this.headerView()
List({ space: 10 }) {
LazyForEach(mDataModel.mBaseDataSource, (item: BaseData, index: number) => {
ListItem() {
if (item as Article) {
if (index === 0) {
BannerView()
} else {
Text(index + " - " + (item as Article).title)
.width('80%')
.height('40vp')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
}
}
.width('100%')
})
}
.width('100%')
.height('100%')
//要用权重,不然高度会有问题
.layoutWeight(1)
.edgeEffect(EdgeEffect.Fade) // 必须设置列表为滑动到边缘无效果
.parallelGesture(PanGesture(this.panOption)
.onActionStart((event: GestureEvent) => {
this.touchYOld = event.offsetX
// console.log(TAG,"onActionStart y:"+this.touchYOld)
})
.onActionUpdate((event: GestureEvent) => {
this.onActionUpdate(event)
// console.log(TAG,"onActionUpdate y:"+event.offsetY)
})
.onActionEnd((event: GestureEvent) => {
})
)
注意:TabContent 包裹 Column{View()+ List().height('100%')},其中List 要使用权重为1,撑满布局,即layoutWeight(1).不然List高度会有问题
静态效果:
动态效果:
实现思路:
头部View跟随List滑动,折叠、伸展,然后搜索框部分进行缩放。List进行手势监听,在滑动过程中对Y轴进行处理,头部View改变高度,MarginTop改变,手势上推下拉判断等,整体代码如下:
private onActionUpdate(event: GestureEvent) {
this.touchYNew = event.offsetY;
let distanceY = this.touchYNew - this.touchYOld;
// 当前手势是否下拉
let isPullAction = distanceY > 0;
console.log(TAG, "是否上拉:" + isPullAction + ` Y:${distanceY}`)
let marginTopY = this.mRowHeight + distanceY
if (isPullAction) {
let titleTopY = this.headerViewHeight + distanceY
//----------------下拉--------------
//stack margin 变化
if (marginTopY < 58) {
this.mRowHeight = marginTopY
} else {
if (this.mRowHeight != 58) {
this.mRowHeight = 58
}
}
//headerView 高度变化
if (titleTopY < 100) {
this.headerViewHeight = titleTopY
this.mRowWidth = 70 + 20 * (50 / titleTopY)
} else {
if (this.headerViewHeight != 100) {
this.headerViewHeight = 100
this.mRowWidth = 90
}
}
console.debug(TAG, "titleTopY:" + titleTopY)
} else {
let titleTopY = this.tileHeight + distanceY
//----------------上推-----------
//stack margin 变化
if (marginTopY > 0) {
this.mRowHeight = marginTopY
} else {
if (this.mRowHeight != 8) {
this.mRowHeight = 8
}
}
//headerView 高度变化
if (titleTopY > 50) {
this.headerViewHeight = titleTopY
this.mRowWidth = 90 - 20 * (50 / titleTopY)
} else {
if (this.headerViewHeight != 50) {
this.headerViewHeight = 50
this.mRowWidth = 70
}
}
console.debug(TAG, "titleTopY:" + titleTopY)
}
}
还要处理搜索框跟随Y轴进行横向伸缩变化,下拉横向变化处理: 宽度 + 可伸缩最大值 * (整体高度 / 高度差变化) , 处理横向伸缩变化。上推则反之处理
总结
通过本次Demo学习,HarmonyOS ArkUI 代码实现布局还是蛮直观的,这次难度中等,主要是实现手势处理,通过滑动List.parallelGesture滑动监听,滑动开始、滑动中、滑动结束处理View高度变化和横向变化处理。官方方法实现简单处理即可得出要想的效果,如果再要实现复杂的可根据自己的效果进行处理,实现方便,代码可读性强。相比Android滑动处理要简单很多了。
鄙人还在学习中有不足,望大佬们多多指教,没有最新API权限有点无奈~