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




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

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

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

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