基于ArkUI的漸變色盤—容器組件的學(xué)習(xí)分享(上)
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
前言
目前HarmonyOS ArkUI 3.0框架的容器組件共有21個(gè),在學(xué)習(xí)完這21個(gè)容器組件后,打算使用盡可能多的容器組件基于HarmonyOS ArkUI 3.0框架去完成一個(gè)實(shí)踐開發(fā),一個(gè)實(shí)踐項(xiàng)目檢驗(yàn)容器組件的學(xué)習(xí)成果就來(lái)了o( ̄︶ ̄)o
本次實(shí)踐項(xiàng)目涉及的容器組件有:Badge(新事件標(biāo)記組件)、Column(沿垂直方向布局的容器)、Flex(彈性布局組件)、List(列表包含一系列相同寬度的列表項(xiàng))、ListItem(用來(lái)展示列表具體item)、Navigator(路由容器組件)、Row(沿水平方向布局容器)、Scroll(可滾動(dòng)的容器組件)、Swiper(滑動(dòng)容器)、Tabs(一種可以通過頁(yè)簽進(jìn)行內(nèi)容視圖切換的容器組件)、TabContent(對(duì)應(yīng)一個(gè)切換頁(yè)簽的內(nèi)容視圖)。
效果圖
歡迎頁(yè)面線性漸變角度添加了漸變徑向漸變




代碼文件結(jié)構(gòu)

正文
一、創(chuàng)建一個(gè)空白工程
1. 安裝和配置DevEco Studio 3.0
2. 創(chuàng)建一個(gè)Empty eTS Ability應(yīng)用
DevEco Studio下載安裝成功后,打開DevEco Studio,點(diǎn)擊左上角的File,點(diǎn)擊New,再選擇New Project,選擇Empty Ability選項(xiàng),點(diǎn)擊Next按鈕。

將文件命名為GradientRamp(文件名不能出現(xiàn)中文或者特殊字符,否則將無(wú)法成功創(chuàng)建項(xiàng)目文件),Project Type勾選Application,選擇保存路徑,Language勾選eTS,選擇API7,設(shè)備勾選Phone,最后點(diǎn)擊Finish按鈕。

3. 準(zhǔn)備工作
在entry>src>main>config.json文件中最下方"launchType": "standard"的后面添加以下代碼,這樣就可以實(shí)現(xiàn)去掉應(yīng)用上方的標(biāo)簽欄了。
config.json最下方部分代碼:
- "metaData": {
- "customizeData": [
- {
- "name": "hwc-theme",
- "value": "androidhwext:style/Theme.Emui.Light.NoTitleBar",
- "extra": ""
- }
- ]
- }
二、 歡迎頁(yè)面
1. 添加背景
Column(沿垂直方向布局的容器)、Flex(彈性布局組件)、Row(沿水平方向布局容器)是最常見的三種容器組件,所以直接說(shuō)明。
Flex
Flex:彈性布局組件
參數(shù):
direction:非必填,子組件在Flex容器上排列的方向,即主軸的方向
- FlexDirection.Row:主軸與行方向一致作為布局模式(默認(rèn))
- FlexDirection.Row:與Row方向相反方向進(jìn)行布局
- FlexDirection.RowReverse:主軸與列方向一致作為布局模式
- FlexDirection.ColumnReverse:與Column相反方向進(jìn)行布局
wrap:非必填,F(xiàn)lex容器是單行/列還是多行/列排列
- FlexWrap.NoWrap:Flex容器的元素單行/列布局,子項(xiàng)允許超出容器(默認(rèn))
- FlexWrap.Wrap:Flex容器的元素多行/列排布,子項(xiàng)允許超出容器
- FlexWrap.WrapReverse:Flex容器的元素反向多行/列排布,子項(xiàng)允許超出容器
justifyContent:非必填,子組件在Flex容器上排列的方向,即主軸的方向子組件在Flex容器主軸上的對(duì)齊格式
- FlexAlign.Start:元素在主軸方向首端對(duì)齊, 第一個(gè)元素與行首對(duì)齊,同時(shí)后續(xù)的元素與前一個(gè)對(duì)齊(默認(rèn))
- FlexAlign.Center:元素在主軸方向中心對(duì)齊,第一個(gè)元素與行首的距離與最后一個(gè)元素與行尾距離相同
- FlexAlign.End:元素在主軸方向尾部對(duì)齊, 最后一個(gè)元素與行尾對(duì)齊,其他元素與后一個(gè)對(duì)齊
- FlexAlign.SpaceBetween:Flex主軸方向均勻分配彈性元素,相鄰元素之間距離相同。 第一個(gè)元素與行首對(duì)齊,最后一個(gè)元素與行尾對(duì)齊
- FlexAlign.SpaceAround:Flex主軸方向均勻分配彈性元素,相鄰元素之間距離相同。 第一個(gè)元素到行首的距離和最后一個(gè)元素到行尾的距離時(shí)相鄰元素之間距離的一半
- FlexAlign.SpaceEvenly:Flex主軸方向元素等間距布局, 相鄰元素之間的間距、第一個(gè)元素與行首的間距、最后一個(gè)元素到行尾的間距都完全一樣
alignItems:非必填,子組件在Flex容器交叉軸上的對(duì)齊格式
- ItemAlign.Auto:使用Flex容器中默認(rèn)配置
- ItemAlign.Start:元素在Flex容器中,交叉軸方向首部對(duì)齊
- ItemAlign.Center:元素在Flex容器中,交叉軸方向居中對(duì)齊
- ItemAlign.End:元素在Flex容器中,交叉軸方向底部對(duì)齊
- ItemAlign.Stretch:元素在Flex容器中,交叉軸方向拉伸填充,在未設(shè)置尺寸時(shí),拉伸到容器尺寸(默認(rèn))
- ItemAlign.Baseline:元素在Flex容器中,交叉軸方向文本基線對(duì)齊
alignContent:非必填,交叉軸中有額外的空間時(shí),多行內(nèi)容的對(duì)齊方式。僅在wrap為Wrap或WrapReverse下生效
- FlexAlign.Start:元素在主軸方向首端對(duì)齊, 第一個(gè)元素與行首對(duì)齊,同時(shí)后續(xù)的元素與前一個(gè)對(duì)齊(默認(rèn))
- FlexAlign.Center:元素在主軸方向中心對(duì)齊,第一個(gè)元素與行首的距離與最后一個(gè)元素與行尾距離相同
- FlexAlign.End:元素在主軸方向尾部對(duì)齊, 最后一個(gè)元素與行尾對(duì)齊,其他元素與后一個(gè)對(duì)齊
- FlexAlign.SpaceBetween:Flex主軸方向均勻分配彈性元素,相鄰元素之間距離相同。 第一個(gè)元素與行首對(duì)齊,最后一個(gè)元素與行尾對(duì)齊
- FlexAlign.SpaceAround:Flex主軸方向均勻分配彈性元素,相鄰元素之間距離相同。 第一個(gè)元素到行首的距離和最后一個(gè)元素到行尾的距離時(shí)相鄰元素之間距離的一半
- FlexAlign.SpaceEvenly:Flex主軸方向元素等間距布局, 相鄰元素之間的間距、第一個(gè)元素與行首的間距、最后一個(gè)元素到行尾的間距都完全一樣
Column
Column:沿垂直方向布局的容器
參數(shù):
space:非必填,縱向布局元素間距,參數(shù)類型為L(zhǎng)ength,即直接填數(shù)字
屬性:
alignItems:設(shè)置子組件在水平方向上的對(duì)齊格式
- HorizontalAlign.Start:按照語(yǔ)言方向起始端對(duì)齊
- HorizontalAlign.Center:居中對(duì)齊,默認(rèn)對(duì)齊方式(默認(rèn))
- HorizontalAlign.End:按照語(yǔ)言方向末端對(duì)齊
Row
Row:沿水平方向布局容器
參數(shù):
space:非必填,橫向布局元素間距,參數(shù)類型為L(zhǎng)ength,即直接填數(shù)字
屬性:
alignItems:在垂直方向上子組件的對(duì)齊格式
- VerticalAlign.Top:頂部對(duì)齊
- VerticalAlign.Center:居中對(duì)齊,默認(rèn)對(duì)齊方式(默認(rèn))
- VerticalAlign.Bottom:底部對(duì)齊
在index.ets文件中,通過Text(‘漸變色盤’)和Text(‘一個(gè)懂你的調(diào)色盤’)可放置文字內(nèi)容。
屬性linearGradient為設(shè)置線性漸變顏色,linearGradient中的angle為漸變角度,設(shè)置為180,即為從上往下漸變,colors則為漸變的顏色。
要值得說(shuō)明的是,如果文本屬性添加了fontFamily(‘華文行楷’)的話,在預(yù)覽器是能看到效果的,但在遠(yuǎn)程模擬器是看不到效果的,因?yàn)檫h(yuǎn)程模擬器內(nèi)是沒有這個(gè)字體的。
index.ets:
- @Entry
- @Component
- struct Index {
- build() {
- Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) {
- Column(){
- Text('漸變色盤')
- .fontColor('#cf6cc9')
- .fontSize(60)
- .fontStyle(FontStyle.Italic)
- .fontWeight(700)
- .fontFamily('華文行楷')
- .textAlign(TextAlign.Center)
- Text('一個(gè)懂你的調(diào)色盤')
- .fontColor('#ee609c')
- .fontSize(40)
- .fontStyle(FontStyle.Italic)
- .fontWeight(600)
- .fontFamily('華文行楷')
- .textAlign(TextAlign.Center)
- .margin({ top: -5 })
- }
- }
- .width('100%')
- .height('100%')
- .linearGradient({
- angle: 120,
- colors: [['#d9ded8', 0], ["#ebc0fd", 1]]
- })
- }
- }
2. 添加動(dòng)畫效果
這里使用的動(dòng)畫效果是通過animateTo顯式動(dòng)畫實(shí)現(xiàn)的。animateTo顯式動(dòng)畫可以設(shè)置組件從狀態(tài)A到狀態(tài)B的變化動(dòng)畫效果,包括樣式、位置信息和節(jié)點(diǎn)的增加刪除等,開發(fā)者無(wú)需關(guān)注變化過程,只需指定起點(diǎn)和終點(diǎn)的狀態(tài)。animateTo還提供播放狀態(tài)的回調(diào)接口,是對(duì)屬性動(dòng)畫的增強(qiáng)與封裝。
添加狀態(tài)變量opacityValue和scaleValue并初始化為0,分別用于表示透明度和放縮的倍數(shù),動(dòng)畫效果中實(shí)現(xiàn)這兩個(gè)數(shù)值從0到1,即可實(shí)現(xiàn)Logo的漸出和放大效果。
定義一個(gè)貝塞爾曲線cubicBezier,Curves.cubicBezier(0.1, 0.2, 1, 1)。由于需要使用到動(dòng)畫能力接口中的插值計(jì)算,故需要導(dǎo)入curves模塊。@ohos.curves模塊提供了線性Curve. Linear、階梯step、三階貝塞爾(cubicBezier)和彈簧(spring)插值曲線的初始化函數(shù),可以根據(jù)入?yún)?chuàng)建一個(gè)插值曲線對(duì)象。
在animateTo顯式動(dòng)畫中,設(shè)置動(dòng)畫時(shí)長(zhǎng)(duration)為2s,延時(shí)(delay)0.1s開始播放,設(shè)置顯示動(dòng)效event的閉包函數(shù)(curve),即起點(diǎn)狀態(tài)到終點(diǎn)狀態(tài)為透明度opacityValue和大小scaleValue從0到1。
index.ets:
- @Entry
- @Component
- struct Index {
- @State private opacityValue: number = 0
- @State private scaleValue: number = 0
- private curve1 = Curves.cubicBezier(0.1, 0.2, 1, 1)
- build() {
- Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) {
- Column(){
- Text('漸變色盤')
- .fontColor('#cf6cc9')
- .fontSize(60)
- .fontStyle(FontStyle.Italic)
- .fontWeight(700)
- .fontFamily('華文行楷')
- .textAlign(TextAlign.Center)
- Text('一個(gè)懂你的調(diào)色盤')
- .fontColor('#ee609c')
- .fontSize(40)
- .fontStyle(FontStyle.Italic)
- .fontWeight(600)
- .fontFamily('華文行楷')
- .textAlign(TextAlign.Center)
- .margin({ top: -5 })
- }
- .scale({ x: this.scaleValue, y: this.scaleValue })
- .opacity(this.opacityValue)
- .onAppear(() => {
- animateTo({
- duration: 2000,
- curve: this.curve1,
- delay: 100,
- }, () => {
- this.opacityValue = 1
- this.scaleValue = 1
- })
- })
- }
- .width('100%')
- .height('100%')
- .linearGradient({
- angle: 120,
- colors: [['#d9ded8', 0], ["#ebc0fd", 1]]
- })
- }
- }
3. 添加動(dòng)畫結(jié)束跳轉(zhuǎn)效果
先創(chuàng)建一個(gè)main.ets文件。
在animateTo顯示動(dòng)畫播放結(jié)束的onFinish回調(diào)接口中,調(diào)用定時(shí)器Timer的setTimeout接口延時(shí)1.5s后,調(diào)用router.replace,顯示mainpage.ets頁(yè)面,其中需要導(dǎo)入router模塊。
index.ets:
- // @ts-nocheck
- import router from '@system.router'
- import Curves from '@ohos.curves'
- @Entry
- @Component
- struct Index {
- @State private opacityValue: number = 0
- @State private scaleValue: number = 0
- private curve1 = Curves.cubicBezier(0.1, 0.2, 1, 1)
- build() {
- Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) {
- Column(){
- Text('漸變色盤')
- .fontColor('#cf6cc9')
- .fontSize(60)
- .fontStyle(FontStyle.Italic)
- .fontWeight(700)
- .fontFamily('華文行楷')
- .textAlign(TextAlign.Center)
- Text('一個(gè)懂你的調(diào)色盤')
- .fontColor('#ee609c')
- .fontSize(40)
- .fontStyle(FontStyle.Italic)
- .fontWeight(600)
- .fontFamily('華文行楷')
- .textAlign(TextAlign.Center)
- .margin({ top: -5 })
- }
- .scale({ x: this.scaleValue, y: this.scaleValue })
- .opacity(this.opacityValue)
- .onAppear(() => {
- animateTo({
- duration: 2000,
- curve: this.curve1,
- delay: 100,
- onFinish: () => {
- setTimeout(() => {
- router.replace({ uri: "pages/main" })
- }, 1500);
- }
- }, () => {
- this.opacityValue = 1
- this.scaleValue = 1
- })
- })
- }
- .width('100%')
- .height('100%')
- .linearGradient({
- angle: 120,
- colors: [['#d9ded8', 0], ["#ebc0fd", 1]]
- })
- }
- }
三、主頁(yè)面
1. 添加背景
主頁(yè)面的背景和歡迎頁(yè)面的背景幾乎一樣,這里就不重復(fù)啰嗦了。
mainp.ets:
- @Entry
- @Component
- struct Main {
- private swiperController: SwiperController = new SwiperController()
- build() {
- Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) {
- }
- .width('100%')
- .height('100%')
- .linearGradient({
- angle: 120,
- colors: [['#d9ded8', 0], ["#ebc0fd", 1]]
- })
- }
- }
2. 添加按鈕
Navigator
Navigator:路由容器組件,提供路由跳轉(zhuǎn)能力
參數(shù):
target:必填,指定跳轉(zhuǎn)目標(biāo)頁(yè)面的路徑,參數(shù)類型為string,即直接填頁(yè)面路徑
type:非必填,指定路由方式
- NavigationType.Push:跳轉(zhuǎn)到應(yīng)用內(nèi)的指定頁(yè)面(默認(rèn))
- NavigationType.Replace:用應(yīng)用內(nèi)的某個(gè)頁(yè)面替換當(dāng)前頁(yè)面,并銷毀被替換的頁(yè)面
- NavigationType.Back:返回上一頁(yè)面或指定的頁(yè)面
屬性:
- active:當(dāng)前路由組件是否處于激活狀態(tài),處于激活狀態(tài)時(shí),會(huì)生效相應(yīng)的路由操作,參數(shù)類型為boolean,即true或false
- params:跳轉(zhuǎn)時(shí)要同時(shí)傳遞到目標(biāo)頁(yè)面的數(shù)據(jù),可在目標(biāo)頁(yè)面使用router.getParams()獲得
從效果圖可以看出按鈕的樣式是一致的,因此我們可以使用裝飾器@Component自定義按鈕。通過Navigator容器組件為按鈕Button添加路由功能。變量str記錄按鈕文本,變量str記錄頁(yè)面路徑,添加狀態(tài)變量active初始化為false,在按鈕的點(diǎn)擊事件中對(duì)狀態(tài)變量active賦值為true,這樣就能當(dāng)點(diǎn)擊按鈕時(shí),使Navigator處于激活狀態(tài)時(shí),生效相應(yīng)的路由操作。
mainp.ets:
- //import router from '@system.router'
- @Entry
- @Component
- struct Main {
- private swiperController: SwiperController = new SwiperController()
- build() {
- Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) {
- setButton({ str: '線性漸變', uri: 'pages/LinearGradient' })
- setButton({ str: '角度漸變', uri: 'pages/SweepGradient' })
- setButton({ str: '徑向漸變', uri: 'pages/RadialGradient' })
- }
- .width('100%')
- .height('100%')
- .linearGradient({
- angle: 120,
- colors: [['#d9ded8', 0], ["#ebc0fd", 1]]
- })
- }
- }
- @Component
- struct setButton{
- @State active: boolean = false
- private str: string
- private uri: string
- build(){
- Navigator({ target: this.uri, type: NavigationType.Push }){
- Button({ type: ButtonType.Normal, stateEffect: true }){
- Text(this.str)
- .fontFamily('方正舒體')
- .fontSize(40)
- .fontWeight(800)
- .fontColor('#FDEB82')
- }
- .width(170)
- .height(80)
- .borderRadius(10)
- .borderColor('#A168FE')
- .borderWidth(2)
- .backgroundColor('#DEB0DF')
- .onClick(() => {
- this.active = true
- })
- }
- .margin(10)
- .active(this.active)
- }
- }
- //通過router添加路由功能
- /*@Component
- struct setButton{
- private str: string
- private uri: string
- build(){
- Button({ type: ButtonType.Normal, stateEffect: true }){
- Text(this.str)
- .fontFamily('方正舒體')
- .fontSize(40)
- .fontWeight(800)
- .fontColor('#FDEB82')
- }
- .width(170)
- .height(80)
- .borderRadius(10)
- .borderColor('#A168FE')
- .borderWidth(2)
- .backgroundColor('#DEB0DF')
- .margin(10).onClick(() => {
- router.push({ uri: this.uri })
- })
- }
- }*/
文章相關(guān)附件可以點(diǎn)擊下面的原文鏈接前往下載
https://harmonyos.51cto.com/resource/1570
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)