接著上一次零基礎快速上手HarmonyOS ArkTS開發3---應用程序框架的繼續往下。
常用基礎組件:
概述:
關于組件的一些基礎概念就里就不多說了,官方有很詳細的說明,而在HarmonyOS按功能分有如下幾大類組件:基礎組件、容器組件、媒體組件、繪制組件、畫布組件。而這里先從最基礎的組件開始學習,有Text、Image、TextInput、Button、LoadingProgress等,以一個最常見的登錄界面來說:
?界面中的是由以下幾個基礎組件搭建而成:
所以下面先來學習這幾個基礎組件。
Image:
用來渲染展示圖片,支持加載本地和網絡圖片,?
基本使用:
對應登錄界面的這個LOGO:
其中是設置了圖片數據源和圖片的大小:
所以下面來看一下圖片相關的設置。
設置圖片數據源:
它的接口形式如下:
Image(src: string | PixelMap | Resource)
其中src是圖片數據源,支持以下三種類型:
1、使用string數據加載圖片:
其中需要注意的是加載網絡圖片時需要在module.json5文件中申明網絡訪問權限:
它不止能加載網絡圖片,還可以支持本地圖片,官方API對其的描述下面貼一下:
當使用相對路徑引用本地圖片時,例如Image("common/test.jpg"),不支持跨包/跨模塊調用該Image組件,建議使用Resource格式來管理需全局使用的圖片資源。
- 支持Base64字符串。格式data:image/[png|jpeg|bmp|webp];base64,[base64 data], 其中[base64 data]為Base64字符串數據。
- 支持file://路徑前綴的字符串。用于讀取本應用安裝目錄下files文件夾下的圖片資源。需要保證目錄包路徑下的文件有可讀權限。
2、PixelMap格式為像素圖,常用于圖片編輯的場景。
3、使用Resource數據加載圖片:
可以跨包/跨模塊訪問資源文件,是訪問本地圖片的推薦方式。
也就是需要將圖片添加到resources的media/rawfile目錄下:
設置圖片大小:
有三種設置方式。
1、使用number數據設置圖片大小:
其中默認單位使用的是“vp”,類似于Android的sp,屏幕密度相關像素,在HarmonyOS中的單位有如下幾種:
2、使用string數據設置圖片大小:
如果是這種形式則需要顯示的加上單位。
3、使用Resource數據設置圖片大小: 【推薦】
此時則需要在float.json文件中定義圖片寬高:
這種方式是最推薦的,統一放到Resource中進行維護管理。
設置縮放類型:
關于圖片通常還會有縮放類型的設置,這里其實官網已經介紹得非常詳細了,這里過一下,比如有這么一張源圖:
而設置縮放類型是如下設置的:
具體不同的縮放類型其對應的效果如下:
1、Contain:保持寬高比進行縮小或者放大,使得圖片完全顯示在顯示邊界內。
2、Cover(默認值):保持寬高比進行縮小或者放大,使得圖片兩邊都大于或等于顯示邊界。
3、Auto:自適應顯示。
4、Fill:不保持寬高比進行放大縮小,使得圖片充滿顯示邊界。
5、ScaleDown:保持寬高比顯示,圖片縮小或者保持不變
6、None:保持原有尺寸顯示。
Text:
基本使用:
對應登錄界面的這個文本:
下面具體來看一下相關的設置:
設置文本內容:
Text(content?: string | Resource)
其中入參:content是文本內容。
1、使用string數據設置文本內容:
2、使用Resource數據設置文本內容:【推薦】
其中文本內容定義在resources下的string.json中:
設置文本大小:fontSize
1、使用number數據設置文本大小:
其默認單位是fp。
2、使用string數據設置文本大小:
此時就需要顯示的指定像素單位了。
3、使用Resource數據設置大小:【推薦】
此時則需要在float.json文件中定義文本大小:
設置文本精細:fontWeight
1、使用number數據設置文本精細:
設置文本的字體粗細,number類型取值[100, 900],取值間隔為100,默認為400,取值越大,字體越粗。
2、使用FontWeight枚舉類型設置文本精細:
它可以取下面這些枚舉類型:
設置文本顏色:
1、使用Color枚舉設置文本顏色:
2、使用number數據設置文本顏色:
其number類型值為16進制整數。
3、使用string數據設置文本顏色:
其數據格式為rgb或rgba顏色。
4、使用Resource設置文本顏色:【推薦】
同樣也需要在color.json中定義文本顏色:
TextInput:
可以輸入單行文本并支持響應輸入事件,比如在登錄界面中的賬號輸入框:
基本使用:
1、設置提示文本:
這種提示功能使用placeholder屬性,另外還可以使用placeholderColor和placeholderFont分別設置提示文本的顏色和樣式,示例代碼如下:
TextInput({ placeholder: '請輸入帳號' }).placeholderColor(0x999999).placeholderFont({ size: 20, weight: FontWeight.Medium, family: 'cursive', style: FontStyle.Italic })
其效果:
2、設置最大輸入字符數:
使用maxLength屬性來進行設置。
3、設置文本框輸入類型:
其類型有:
Button:
基本使用:
1、設置按鈕樣式:
其中說一下按鈕的樣式,有如下幾種:
容器組件:
在Android中有比較經典的四大布局組件(LinearLayout、RelativeLayout、FrameLayout、ConstraintLayout),這些都是父布局,類似有在Harmony中也有這樣的容器組件,提供了Column和Row容器來實現線性布局,還是以登錄界面為例,以控件的角度來將頁面的布局可以表示為:
可以看到整體的布局是按著從上到下的順序來排列的,所以此時可以由Column容器來進行布局:
而有些元素是需要水平排列的,此時就可以使用Row容器來進行布局:
布局基礎知識:
主軸和交叉軸概念:
在布局容器中,默認存在兩根軸,分別是主軸和交叉軸,這兩個軸始終是相互垂直的。不同的容器中主軸的方向不一樣的。
主軸:
在Column容器中的子組件是按照從上到下的垂直方向布局的,其主軸的方向是垂直方向;在Row容器中的組件是按照從左到右的水平方向布局的,其主軸的方向是水平方向。
交叉軸:
與主軸垂直相交的軸線,如果主軸是垂直方向,則交叉軸就是水平方向;如果主軸是水平方向,則交叉軸是垂直方向。
屬性介紹:
了解了布局容器的主軸和交叉軸概念之后,有助于我們更好地理解子組件在主軸和交叉軸的排列方式。這里需要學習兩個屬性:justifyContent和alignItems,其具體的含義如下:
如果不理解主軸和交叉軸的概念,那么對于這兩個屬性的運用就會很迷糊。 對于這兩個屬性的使用官方其實已經解釋得非常詳細了,這里照著官方的整體再來學習一遍。
1、主軸方向的對齊(justifyContent):
對于justifyContent屬性,它接收的參數類型為FlexAlign,有如下幾個值:
光看這些文字對于這些值的設置效果還是非常抽象的,所以下面看一下每一種參數類型設置之后的效果,這樣就比較容易理解了:
1、Start:元素在主軸方向首端對齊,第一個元素與行首對齊,同時后續的元素與前一個對齊。
2、Center:元素在主軸方向中心對齊,第一個元素與行首的距離以及最后一個元素與行尾距離相同。
3、End:元素在主軸方向尾部對齊,最后一個元素與行尾對齊,其他元素與后一個對齊。
4、SpaceBetween:元素在主軸方向均勻分配彈性元素,相鄰元素之間距離相同。 第一個元素與行首對齊,最后一個元素與行尾對齊。
5、SpaceAround:元素在主軸方向均勻分配彈性元素,相鄰元素之間距離相同。 第一個元素到行首的距離和最后一個元素到行尾的距離是相鄰元素之間距離的一半。
6、SpaceEvenly:元素在主軸方向等間距布局,無論是相鄰元素還是邊界元素到容器的間距都一樣。
2、交叉軸方向的對齊(alignItems):
對于Column容器它的交叉軸是水平方向,所以參數類型為HorizontalAlign(水平對齊),有如下幾種對齊方式:
1、Start:設置子組件在水平方向上按照起始端對齊。
2、Center(默認值):設置子組件在水平方向上居中對齊。
3、End:設置子組件在水平方向上按照末端對齊。
而對于Row容器的交叉軸是垂直方向,所以參數為VerticalAlign(垂直對齊),它有如下幾種對齊方式:
1、Top:設置子組件在垂直方向上居頂部對齊。
2、Center(默認值):設置子組件在豎直方向上居中對齊。
3、Bottom:設置子組件在豎直方向上居底部對齊。
接口介紹:
對于Column和Row容器都有一個可選參數space,表示子組件在主軸方向上的間距:
其效果如下:
實踐:構建登錄頁面:
接下來咱們則用學過的布局來實現開篇所示的這么一個登錄靜態界面,實操一把:
1、新建工程:
其項目名稱直接校仿官方的codelabs的https://gitee.com/harmonyos/codelabs/tree/master/ArkTSComponents
2、新建登錄頁面文件:
@Entry
@Component
struct LoginPage {@State message: string = 'Login Page'build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)}.width('100%')}.height('100%')}
}
先讓其可以顯示出來,此時需要修改這里的加載頁面:
運行:
界面構建:
接下來則來進行界面的構建:
1、構建Logo區域:
整個是一個上下布局,所以就需要用到這次所學的Column容器組件了:
其中會用到一些常量,這里為了省事,直接從官方的源碼中拷過來了:
CommonConstants.ets:
/*** Common constants for all features.*/
export default class CommonConstants {/*** Input length of the account.*/static readonly INPUT_ACCOUNT_LENGTH = 11;/*** Input length of the password.*/static readonly INPUT_PASSWORD_LENGTH = 8;/*** Left padding of the input box*/static readonly INPUT_PADDING_LEFT = 0;/*** Delay time of simulated login*/static readonly LOGIN_DELAY_TIME = 2000;/*** Common Spacing of Components*/static readonly COMMON_SPACE = 12;/*** Title text of the home page*/static readonly HOME_TITLE = '首頁';/*** Title text of the setting page*/static readonly MINE_TITLE = '我的';/*** Spacing of other login methods*/static readonly LOGIN_METHODS_SPACE = 44;/*** The width or height of the component is spread across the parent component.*/static readonly FULL_PARENT = '100%';/*** The width of button*/static readonly BUTTON_WIDTH = '90%';/*** The width of setting list*/static readonly SET_LIST_WIDTH = '42%';/*** Home tab index*/static readonly HOME_TAB_INDEX = 0;/*** Mine tab index*/static readonly MINE_TAB_INDEX = 1;
}
float.json:
{"float": [{"name": "logo_image_size","value": "78vp"},{"name": "logo_margin_top","value": "100vp"},{"name": "logo_margin_bottom","value": "8vp"},{"name": "page_title_text_size","value": "24fp"},{"name": "normal_text_size","value": "16fp"},{"name": "big_text_size","value": "18fp"},{"name": "small_text_size","value": "14fp"},{"name": "little_text_size","value": "12fp"},{"name": "login_more_margin_bottom","value": "30vp"},{"name": "login_more_margin_top","value": "8vp"},{"name": "login_input_height","value": "45vp"},{"name": "forgot_margin_top","value": "8vp"},{"name": "input_margin_top","value": "12vp"},{"name": "line_height","value": "1vp"},{"name": "login_button_height","value": "40vp"},{"name": "login_button_margin_top","value": "87vp"},{"name": "login_button_margin_bottom","value": "12vp"},{"name": "vertical_line_margin","value": "15vp"},{"name": "login_progress_size","value": "30vp"},{"name": "login_progress_margin_top","value": "20vp"},{"name": "other_login_margin_top","value": "50vp"},{"name": "other_login_margin_bottom","value": "12vp"},{"name": "login_page_padding_bottom","value": "24vp"},{"name": "other_login_image_size","value": "48vp"},{"name": "page_padding_hor","value": "12vp"},{"name": "mainPage_baseTab_top","value": "4vp"},{"name": "mainPage_baseTab_margin","value": "8vp"},{"name": "mainPage_padding","value": "12vp"},{"name": "mainPage_barHeight","value": "56vp"},{"name": "mainPage_baseTab_size","value": "25vp"},{"name": "main_tab_fontSize","value": "10fp"},{"name": "mainPage_tabTitles_margin","value": "12vp"},{"name": "mainPage_tabTitles_padding","value": "12vp"},{"name": "home_swiper_borderRadius","value": "16vp"},{"name": "home_swiper_margin","value": "24vp"},{"name": "home_grid_columnsGap","value": "8vp"},{"name": "home_grid_rowGap","value": "12vp"},{"name": "home_grid_padding","value": "12vp"},{"name": "home_grid_height","value": "124vp"},{"name": "home_grid_margin","value": "10vp"},{"name": "home_list_margin","value": "4vp"},{"name": "home_list_padding","value": "8vp"},{"name": "home_grid_borderRadius","value": "24vp"},{"name": "home_text_margin","value": "12vp"},{"name": "home_backgroundImage_borderRadius","value": "12vp"},{"name": "home_secondGrid_height","value": "260vp"},{"name": "home_secondGrid_margin","value": "10vp"},{"name": "home_homeCell_size","value": "24vp"},{"name": "home_homeCell_margin","value": "4vp"},{"name": "home_homeCell_width","value": "80vp"},{"name": "home_homeCell_height","value": "80vp"},{"name": "setting_name_margin","value": "4vp"},{"name": "setting_account_margin","value": "24vp"},{"name": "setting_account_size","value": "48vp"},{"name": "setting_account_fontSize","value": "20fp"},{"name": "setting_account_text_height","value": "28vp"},{"name": "setting_account_height","value": "96vp"},{"name": "setting_account_padding","value": "24vp"},{"name": "setting_account_borderRadius","value": "16vp"},{"name": "setting_list_height","value": "48vp"},{"name": "setting_list_padding","value": "4vp"},{"name": "setting_list_borderRadius","value": "16vp"},{"name": "setting_list_startMargin","value": "42vp"},{"name": "setting_list_endMargin","value": "24vp"},{"name": "setting_list_strokeWidth","value": "0.25vp"},{"name": "setting_button_bottom","value": "55vp"},{"name": "setting_size","value": "22vp"},{"name": "setting_padding","value": "10vp"},{"name": "setting_jump_width","value": "12vp"},{"name": "setting_jump_height","value": "24vp"},{"name": "setting_settingCell_left","value": "8vp"},{"name": "setting_settingCell_right","value": "22vp"}]
}
color.json:
{"color": [{"name": "start_window_background","value": "#FFFFFF"},{"name": "white","value": "#FFFFFF"},{"name": "background","value": "#F1F3F5"},{"name": "title_text_color","value": "#182431"},{"name": "login_more_text_color","value": "#99182431"},{"name": "placeholder_color","value": "#99182431"},{"name": "line_color","value": "#33182431"},{"name": "login_button_color","value": "#007DFF"},{"name": "login_blue_text_color","value": "#007DFF"},{"name": "other_login_text_color","value": "#838D97"},{"name": "loading_color","value": "#182431"},{"name": "mainPage_selected","value": "#1698CE"},{"name": "mainPage_normal","value": "#6B6B6B"},{"name": "mainPage_backgroundColor","value": "#F1F3F5"},{"name": "home_grid_fontColor","value": "#99182431"},{"name": "setting_button_backgroundColor","value": "#E5E8EA"},{"name": "setting_button_fontColor","value": "#FA2A2D"}]
}
此時效果如下:
接下來修改布局:
Image($r('app.media.logo')).width($r('app.float.logo_image_size')).height($r('app.float.logo_image_size')).margin({ top: $r('app.float.logo_margin_top'), bottom: $r('app.float.logo_margin_bottom') })Text($r('app.string.login_page')).fontSize($r('app.float.page_title_text_size')).fontWeight(FontWeight.Medium).fontColor($r('app.color.title_text_color'))Text($r('app.string.login_more')).fontSize($r('app.float.normal_text_size')).fontColor($r('app.color.login_more_text_color')).margin({ bottom: $r('app.float.login_more_margin_bottom'), top: $r('app.float.login_more_margin_top') })
其效果如下:
2、構建用戶名密碼輸入框區域:
/* 用戶名、密碼輸入框 */TextInput({ placeholder: $r('app.string.account') }).maxLength(CommonConstants.INPUT_ACCOUNT_LENGTH).type(InputType.Number).placeholderColor($r('app.color.placeholder_color')).height($r('app.float.login_input_height')).fontSize($r('app.float.big_text_size')).backgroundColor($r('app.color.background')).width(CommonConstants.FULL_PARENT).padding({ left: CommonConstants.INPUT_PADDING_LEFT }).margin({ top: $r('app.float.input_margin_top') })Line().width(CommonConstants.FULL_PARENT).height($r('app.float.line_height')).backgroundColor($r('app.color.line_color'))TextInput({ placeholder: $r('app.string.password') }).maxLength(CommonConstants.INPUT_PASSWORD_LENGTH).type(InputType.Password).placeholderColor($r('app.color.placeholder_color')).height($r('app.float.login_input_height')).fontSize($r('app.float.big_text_size')).backgroundColor($r('app.color.background')).width(CommonConstants.FULL_PARENT).padding({ left: CommonConstants.INPUT_PADDING_LEFT }).margin({ top: $r('app.float.input_margin_top') })Line().width(CommonConstants.FULL_PARENT).height($r('app.float.line_height')).backgroundColor($r('app.color.line_color'))
其效果如下:
這里面是純熟能生巧的代碼,也非常好理解,所以就不過多解釋了,照著官方的demo擼一擼就成,不過這里跟官網的源碼有如下區別:
官方的源碼寫得非常的精練,咱們來學習一下這樣的寫法,其核心就是對相同的屬性做了一個封裝,所以我這邊故意寫得這么臃腫,好來看一下整個的優化過程,先來看目前代碼存在什么問題?
所以有必要對其公共的屬性進行一個抽取,具體如何抽取呢?看下官方的代碼便知,先來將TextInput中的公共屬性抽取一下:
把它抽取到一個函數中:
此時函數報錯了:
找不到相關的屬性,這個也容易理解,本身這些屬性是來自于控件當中的,怎么可以在一個全新的函數中知道這些屬性呢?那如何解決呢?這里就需要用到這么一個裝飾器了@Extend:
先來看一下它的定義:
關于它更加詳細的使用可以參考:文檔中心,好此時對于TextInput的代碼就可以精簡成這樣了:
同樣的,對于Line也可以照此進行封裝:
3、構建短信驗證碼及忘記密碼區域:
接下來則來構建這個區域了:
這里則需要使用到水平布局Row容器了,如下:
此時運行看一下:
接下來則需要讓這倆元素分散在兩端,此時就需要用到上面所學的主軸方向的元素對齊了,如下:
此時運行如下:
4、構建登錄注冊按鈕區域:
接下來則來構建這個區域:
/* 登錄注冊按鈕區域 */Button($r('app.string.login'), { type: ButtonType.Capsule }).width(CommonConstants.BUTTON_WIDTH).height($r('app.float.login_button_height')).fontSize($r('app.float.normal_text_size')).fontWeight(FontWeight.Medium).backgroundColor($r('app.color.login_button_color')).margin({ top: $r('app.float.login_button_margin_top'), bottom: $r('app.float.login_button_margin_bottom') })Text($r('app.string.register_account')).fontColor($r('app.color.login_blue_text_color')).fontSize($r('app.float.normal_text_size')).fontWeight(FontWeight.Medium)
運行:
這塊沒有什么好解釋的。
5、構建其他登錄方式區域:
還剩最后一個底部區域木有構建:
其中涉及到一些資源圖,這里可以直接從官方源碼中拷至工程中:
此時可以看到是長這樣:
貌似跟預期的有一點區域,應該是整個區域是靠底部,如何讓它靠在最底部呢?這里需要用到空白填充組件Blank,如下:
此時再運行就如預期了,這里來了解一下該填充組件:文檔中心
看文字是不是還不太好理解,這里再看一下官方文檔提供的示例就明白了:
另外此代碼還有一個可以優化的點,就是:
代碼都一樣,除了按鈕的圖片資源不一樣:
代碼可以進行一次封裝么?可以的,可以看下官方的寫法,相當的精練:
所以照著優化一下:
此時代碼就可以這樣寫了:
此時又有一個知識點,那@Builder這是啥裝飾器呢?這里可以參考它:文檔中心,看一下它的說明:
看一下它的簡單使用示例:
也就是如果在界面中有重復使用的元素,就可以使用該裝飾器對其進行一個封裝,提高代碼的維護性。
總結:
至此,這里通過所學完成了官方登錄頁面的搭建,按著視頻的總結一下此次所學:
1、垂直布局使用Column容器;
2、水平布局使用Row容器;
3、space參數設置子組件在主軸方向上的對齊;
4、justContent屬性設置子組件在主軸方向上的對齊;
5、alignItems屬性設置子組件在交叉軸方向上的對齊;
好長一段時間沒有更新了,人越來越懶~~
??關注個人公眾號,獲得實時推送