“本文正在参加华为鸿蒙有奖征文征文活动”

构建类似抖音的视频布局与动画
自学鸿蒙也有一段时间了,论语中有句话叫温故而知新,可以为师矣。所以在忙完手头工作之后,我觉得有必要再写一写鸿蒙代码了。士兵突击中有句经典的台词 好的枪手都是子弹喂出来的,所以我坚信好的程序员都是在N多次的代码实践中成长起来的。
闲话少说,进入正题。本文将完成抖音APP视频模块的部分仿写。围绕着静态布局分析及实践,简单的旋转动画来展开聊聊鸿蒙应用开发。
静态布局分析及实践
布局分析
根据分析抖音的布局看出,分为三大部分:
- 最外层容器也是视频播放区域
- 底部的昵称和视频描述文字
- 右侧头像 点赞评论收藏按钮等竖着排列的按钮
代码实践
整体布局搭建
作为一个前端,这种布局我第一个想到的就是子绝父相定位。但是鸿蒙文档中并没有定位的这个概念,在他文章中叫做堆叠。于是我们就要使用Stack这个堆叠容器。官方对于该容器的描述为:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。所以按照我的理解就是子组件按照从上向下的顺序层级递增。
代码
// 与底部采用左下对齐
Stack({
alignContent: Alignment.BottomStart
}) {
// 视频主体与右侧采用右下对齐
Stack({
alignContent: Alignment.BottomEnd
}) {
// 视频主体
Text('视频主体')
.width('100%')
.height('100%')
.backgroundColor(Color.Red)
// 右侧功能区
Text('右侧功能区')
.width('50vp')
.height('50%')
.backgroundColor(Color.Blue)
}
// 底部昵称以及描述
Text('底部区域')
.width('100%')
.height('30vp')
.backgroundColor(Color.Green)
}
效果
视频布局
由于视频是可以上下滑动切换的所以我觉得使用Swiper+Video这两个组件来写应该是可以的
代码
// 视频主体
Video({
src: item,
previewUri: this.previewUris,
controller: this.controller
})
.muted(false)//设置是否静音
.controls(false)//设置是否显示默认控制条
.autoPlay(true)//设置是否自动播放
.loop(true)//设置是否循环播放
.objectFit(ImageFit.Contain) // 设置视频适配模式
右侧布局
右侧内容还是占整个模块不少的比重,我将右侧拆分为三个组件
-
头像组件,使用Stack布局,细分为头像图片和点击关注按钮两部分
在Stack定位布局中,一个头像Image 一个点赞按钮Image,通过margin将点赞按钮置于头像的下面边缘处
代码
// 头像关注
@Component
struct Via {
build() {
Stack() {
Image($r('app.media.touxiang'))
.width('45vp')
.height('45vp')
.border({
width: '2vp',
color: '#ffffff',
style: BorderStyle.Solid
})
.borderRadius('45vp')
Image($r('app.media.add'))
.width('20vp')
.height('20vp')
.margin({top: '45vp'})
}
}
}
-
点赞收藏分享按钮,使用Cloumn将icon和文字上下布局
Column布局是上下布局方式,自组件自上而下排成一列,以下代码中使用一个Image容器 一个Text容器,并在组件内接受icon名称以及text文本,以便达到点赞,评论,收藏,分享按钮的组件复用
代码
// icon & 数量上下布局
@Component
struct IconAndText {
@Prop icon:String = ''
@Prop text:String = ''
build() {
Column() {
Image($r(`app.media.${this.icon}`))
.width('30vp')
.margin({
top: '5vp'
})
.opacity(0.8)
Text(`${this.text}`)
.fontColor('#ffffff')
}.margin({top:'10vp'})
}
}
-
右下角音乐旋转组件,其实就是个自转的图片
使用animation属性动画,在.onApper()方法中改变rotatevalue的值,利用animation属性动画值改变自动执行动画特性从而达到动画的执行。在animation方法中iterations属性的值为-1 从而达到循环执行目的
代码
// 背景音乐入口
@Component
struct MusicEntry {
@State rotateValue:number = 0
aboutToAppear() {
}
build(){
Image($r('app.media.touxiang'))
.width('40vp')
.height('40vp')
.borderRadius('45vp')
.margin({top:'15vp'})
.rotate({ angle: this.rotateValue })
.animation({
curve: Curve.Linear,
duration: 3500,
iterations: -1
})
.onAppear(() => {
this.rotateValue = 360
})
}
}
底部布局
底部布局就是两行文字上下布局 非常的简单
同样是使用Column布局 使两个Text容器上下排列,并且在第二个Text容器中给一个上外边距,达到两段文字隔开距离的效果
代码
// 底部昵称
@Component
struct FooterNikeName {
build() {
Column() {
Text('@把梦想揉碎')
.fontColor('#FFFFFF')
.fontSize('18vp')
.fontWeight(FontWeight.Medium)
Text('哈哈哈,这条视频也太有意思了吧')
.fontColor('#FFFFFF')
.margin({top: '10vp'})
.fontSize('15vp')
}
.margin({left: '10vp',bottom: '10vp'})
.alignItems(HorizontalAlign.Start)
}
}
最终效果GIF
鸿蒙应用带来的思考
ArkUI的组件化设计让我深刻体会到组件复用的重要性。在这个项目中,我将右侧功能区拆分为多个独立组件,如头像关注组件、点赞收藏组件等,这种做法不仅提高了代码的可读性和维护性,还便于在未来的开发中进行复用。通过这种方式,能够在保证功能完整的前提下,保持代码结构的清晰和模块化。
写在最后
通过本次仿写抖音视频布局的实践,我进一步熟悉了HarmonyOS中的ArkUI框架,也加深了对鸿蒙生态系统的理解。这次开发的过程让我认识到,不论是前端开发还是移动端开发,掌握一个框架的核心思想和布局模型至关重要。此外,通过不断的代码实践和总结,我也看到了自己在开发技能上的进步。
希望这篇文章能为其他开发者提供一些帮助和启发。未来,我将继续深入学习HarmonyOS,并分享更多的开发经验和心得。让我们一起在鸿蒙生态的广阔天地中探索更多的可能性。