編程范式:命令式->聲明式
以一個(gè)卡片的實(shí)現(xiàn)做下講解
命令式
簡單講就是需要開發(fā)用代碼一步一步進(jìn)行布局湃缎,這個(gè)過程需要開發(fā)全程參與昌渤。
- Objective-C
UIView *cardView = [[UIView alloc] init];
cardView.backgroundColor = [UIColor whiteColor];
cardView.layer.cornerRadius = 16;
cardView.clipsToBounds = YES;
[self.view addSubview:cardView];
[cardView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(16);
make.right.mas_offset(-16);
make.height.mas_equalTo(116);
make.top.mas_equalTo(100);
}];
NSString *imgUrl = @"https://ke-image.ljcdn.com//110000-inspection//pc1_nBllrJgGj_1.jpg.280x210.jpg";
UIImageView *imgView = [[UIImageView alloc] init];
imgView.backgroundColor = [UIColor lightGrayColor];
[imgView sd_setImageWithURL:[NSURL URLWithString:imgUrl]];
[cardView addSubview:imgView];
[imgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.mas_offset(0);
make.left.mas_equalTo(0);
make.width.mas_equalTo(107);
}];
UILabel *titleLbl = [[UILabel alloc] init];
titleLbl.font = [UIFont systemFontOfSize:14 weight:UIFontWeightBold];
titleLbl.textColor = [UIColor blackColor];
titleLbl.text = @"萬柳書院新一區(qū) 南北向滿五唯一";
[cardView addSubview:titleLbl];
[titleLbl mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(imgView.mas_right).mas_offset(12);
make.right.mas_offset(-12);
make.top.mas_equalTo(16);
}];
UILabel *subTitleLbl = [[UILabel alloc] init];
subTitleLbl.textColor = [UIColor blackColor];
subTitleLbl.font = [UIFont systemFontOfSize:12 weight:UIFontWeightRegular];
subTitleLbl.text = @"4室2廳/278.35㎡/南 北/萬柳書院";
[cardView addSubview:subTitleLbl];
[subTitleLbl mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(titleLbl);
make.top.mas_equalTo(titleLbl.mas_bottom).mas_offset(8);
}];
UILabel *priceLbl = [[UILabel alloc] init];
priceLbl.font = [UIFont systemFontOfSize:14 weight:UIFontWeightBold];
priceLbl.textColor = [UIColor redColor];
priceLbl.text = @"4238萬";
[cardView addSubview:priceLbl];
[priceLbl mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(titleLbl);
make.bottom.mas_offset(-16);
}];
UILabel *avgPriceLbl = [[UILabel alloc] init];
avgPriceLbl.textColor = [UIColor lightGrayColor];
avgPriceLbl.font = [UIFont systemFontOfSize:12 weight:UIFontWeightRegular];
avgPriceLbl.text = @"155,445元/平";
[cardView addSubview:avgPriceLbl];
[avgPriceLbl mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(priceLbl.mas_right).mas_offset(2);
make.right.mas_lessThanOrEqualTo(titleLbl.mas_right);
make.bottom.mas_equalTo(priceLbl);
}];
聲明式
聲明式則是由開發(fā)使用語言描述UI頁面長什么樣子腌逢,之后全權(quán)交給引擎去做
- 對頁面結(jié)構(gòu)進(jìn)行大的拆解扭弧。比如上面卡片分左右兩大部分
- 選用合適的容器組件進(jìn)行頁面描述
- 針對拆解出來的每個(gè)部分重復(fù)上面的兩步,直到無法拆解只能使用基本組件描述為止
比如上面的卡片可以進(jìn)行如下的拆分
- 整體是一個(gè)Row容器著恩,分為左右兩大部分洒嗤,左邊是圖片箫荡,右邊是一個(gè)Column容器
- 右邊Column容器又拆分為兩大部分,上面是標(biāo)題和描述渔隶,下面是價(jià)格羔挡。兩部分按照space-between布局
- 上面的標(biāo)題和描述作為一個(gè)整體,里面拆分成Column的兩個(gè)組件
- 下面價(jià)格可以直接使用系統(tǒng)組件Text
ReactNative
<View
style={{
borderRadius: 8,
marginHorizontal: 16,
flexDirection: 'row',
backgroundColor: 'white',
overflow: 'hidden',
height: 116,
}}>
<Image
source={{
uri: 'https://ke-image.ljcdn.com//110000-inspection//pc1_nBllrJgGj_1.jpg.280x210.jpg',
}}
style={{width: 107, backgroundColor: '#eee'}}
/>
<View
style={{
marginVertical: 16,
marginHorizontal: 12,
flex: 1,
justifyContent: 'space-between',
}}>
<View>
<Text style={{fontSize: 14, color: '#222', fontWeight: '500'}}>
萬柳書院新一區(qū) 南北向滿五唯一
</Text>
<Text style={{fontSize: 11, color: '#222', marginTop: 8}}>
4室2廳/278.35㎡/南 北/萬柳書院
</Text>
</View>
<View
style={{flexDirection: 'row', marginTop: 8, alignItems: 'flex-end'}}>
<Text
style={{
fontSize: 17,
color: '#E62222',
fontWeight: 'bold',
}}>
4238萬
</Text>
<Text style={{fontSize: 11, color: '#999', marginLeft: 6}}>
155,445元/平
</Text>
</View>
</View>
</View>
SwiftUI
HStack(spacing:0) {
AsyncImage(url: URL(string: "https://ke-image.ljcdn.com//110000-inspection//pc1_nBllrJgGj_1.jpg.280x210.jpg"))
.frame(width:107)
.aspectRatio(contentMode: .fill)
.clipped()
VStack(alignment: .leading,
spacing:0) {
VStack(alignment: .leading,
spacing:0) {
Text("萬柳書院新一區(qū) 南北向滿五唯一")
.lineLimit(1)
.font(.system(size: 14))
.foregroundColor(.black)
.fontWeight(.bold)
Text("4室2廳/278.35㎡/南 北/萬柳書院")
.lineLimit(1)
.font(.system(size: 12))
.foregroundColor(.black)
.padding(.top, 8)
}
Spacer()
HStack(alignment: .bottom,
spacing:2) {
Text("4238萬")
.font(.system(size: 14))
.foregroundColor(.red)
.fontWeight(.bold)
Text("155,445元/平")
.font(.system(size: 12))
.foregroundColor(.secondary)
.padding(.leading, 2)
}
}
.padding(.vertical, 16)
.padding(.horizontal, 12)
Spacer()
}
.frame(height: 116)
.background(.white)
.clipShape(RoundedRectangle(cornerRadius: 8))
.padding(.horizontal, 16)
}
ArkUI
Row() {
Row() {
Image("https://ke-image.ljcdn.com//110000-inspection//pc1_nBllrJgGj_1.jpg.280x210.jpg")
.width(107)
.height("100%")
.objectFit(ImageFit.Cover)
Column() {
Column() {
Text("柳書院新一區(qū) 南北向滿五唯一")
.fontSize(16)
.fontColor("#222")
.maxLines(1)
Text("4室2廳/278.35㎡/南 北/萬柳書院")
.fontSize(14)
.fontColor("#222")
.maxLines(1)
.margin({ top: 8 })
}
.alignItems(HorizontalAlign.Start)
Row() {
Text("4238萬")
.fontSize(15)
.fontColor("#E62222")
.fontWeight(FontWeight.Bold)
Text("155,445元/平")
.fontSize(13)
.fontColor("#222")
.margin({ left: 2 })
}
.justifyContent(FlexAlign.Start)
.alignItems(VerticalAlign.Bottom)
}
.width("100%")
.height("100%")
.padding({ top: 16, bottom: 16, left: 12, right: 12 })
.alignItems(HorizontalAlign.Start)
.justifyContent(FlexAlign.SpaceBetween)
}
.borderRadius(8)
.margin({ left: 16, right: 16 })
.backgroundColor(Color.White)
.justifyContent(FlexAlign.Start)
.clip(true)
}
.height(116)
.width("100%")
小結(jié)
從上面的例子可以看出來间唉,聲明式語法只需要我們描述UI長什么樣就行绞灼。不需要做太多布局計(jì)算的工作,讓我們少掉一些頭發(fā)
ArkUI和SwiftUI的語法最像终吼,甚至它們的狀態(tài)管理也很像镀赌,都是提供了狀態(tài)綁定和監(jiān)聽機(jī)制來更新UI樣式
聲明式UI布局原理簡述
Flutter中Widget的布局原理參考
Flutter中Widget的布局原理如下圖所示氯哮。想了解更多Flutter的布局原理可以查看 深入理解 Flutter 布局約束
SwiftUI中的View布局原理參考
SwiftUI中的布局原理可以參考下圖际跪。想了解細(xì)節(jié),可參考 SwiftUI 中布局的工作原理
小結(jié)
聲明式布局想要布局子視圖都會經(jīng)歷由上到下的一個(gè)過程喉钢,只有知道了子視圖的大小之后才能根據(jù)對齊方式將子視圖放置在準(zhǔn)確的位置姆打。
聲明式布局幾乎都是下面這個(gè)套路
- 父視圖給子視圖一個(gè)布局約束(作為Root的根視圖默認(rèn)是充滿屏幕的,它給子視圖的約束就是屏幕大谐λ洹)
- 子視圖渲染并將自身大小返回給父視圖
- 父視圖根據(jù)子視圖的大小和設(shè)定的對齊方式計(jì)算要放置的位置
- 子視圖的布局也遵循以上三步進(jìn)行遞歸幔戏。整個(gè)過程是深度優(yōu)先的
ArkUI
ArkUI官方鏈接
方舟開發(fā)框架(簡稱ArkUI)是鴻蒙開發(fā)的UI框架,提供如下兩種開發(fā)范式税课,我們 只學(xué)聲明式開發(fā)范式
- 基于ArkTS的聲明式開發(fā)范式
- 兼容JS的類Web開發(fā)范式
整體架構(gòu)圖
我們使用ArkTS寫完頁面描述后闲延,交給語言運(yùn)行時(shí)進(jìn)行語法解析痊剖,再之后由C++編寫的后端引擎將UI轉(zhuǎn)換為渲染指令交給渲染引擎繪制到屏幕上
ArkUI語法初見
- ArkTS對TypeScript語言進(jìn)行擴(kuò)展,提供值類型結(jié)構(gòu)struct垒玲。
- struct定義自定義組件陆馁,必須搭配Component或者CustomDialog使用
- ArkUI中組件定義和狀態(tài)管理都是通過裝飾器來做的。TS中的裝飾器主要有類裝飾器合愈、屬性裝飾器叮贩、方法裝飾器以及參數(shù)裝飾器四種
- 事件方法和屬性方法只是方法的入?yún)⒉灰粯樱粋€(gè)是基本值或者表達(dá)式值佛析,一個(gè)是函數(shù)益老。
- 在TS中函數(shù)我們就把函數(shù)當(dāng)成變量來用就行,只不過普通變量是存儲一個(gè)類型的值寸莫,而函數(shù)用來存儲一個(gè)輸入到輸出的轉(zhuǎn)變過程
- 還記得我們上面說的描述UI嘛捺萌,在這里就在build函數(shù)中描述”炀ィ框架會自動調(diào)用build互婿,不需要我們手動調(diào)用
從代碼到UI顯示的整體渲染流程
ArkUI的渲染分為兩大情況
從創(chuàng)建到顯示(①~⑤)
① 通過devEco將源碼編譯成帶類型標(biāo)識的字節(jié)碼文件,同時(shí)攜帶創(chuàng)建這個(gè)結(jié)構(gòu)所需信息的指令流
② 通過跨語言調(diào)用生成C++層的Component樹辽狈。這一步只是把ArkTS描述轉(zhuǎn)變成了使用C++描述
③ 通過Component樹生成Element樹慈参,Element是Component的實(shí)例,用于表示一個(gè)具體的組件節(jié)點(diǎn)刮萌。界面在運(yùn)行時(shí)的樹形結(jié)構(gòu)就是通過Element樹來維持的驮配,同時(shí)自動更新的diff算法也是依賴Element樹來減少復(fù)雜度的
④ 對于每個(gè)可顯示的Element都會為其創(chuàng)建對應(yīng)的RenderNode。RenderNode負(fù)責(zé)一個(gè)節(jié)點(diǎn)的顯示信息着茸,它形成的Render樹維護(hù)著整個(gè)界面渲染需要用到的信息壮锻,包括位置、大小涮阔、繪制命令等猜绣。后續(xù)的布局、繪制都是在Render樹上進(jìn)行的
⑤ 實(shí)現(xiàn)真正的渲染并顯示繪制結(jié)果
按鈕點(diǎn)擊到更新顯示(⑥~?)
⑥ 點(diǎn)擊事件傳遞到組件敬特,組件的onClick事件方法被觸發(fā)執(zhí)行
⑦ 由于onClick事件方法中@State注解過的變量改變了掰邢,相應(yīng)getter/setter函數(shù)會被觸發(fā)
⑧ 狀態(tài)管理模塊定位出關(guān)聯(lián)的UI組件
⑨ 狀態(tài)管理模塊更新相應(yīng)的Element樹的信息
⑩ 更新相應(yīng)的UI組件的渲染信息
? 界面顯示,與⑤類似
盒子模型
上面我們說的布局原理伟阔,子視圖上報(bào)給父視圖自身大小的值是指 組件內(nèi)容區(qū)的大小
ArkUI中常用布局容器
如何選擇使用哪種布局
線性布局(Row/Column)
- 線性布局的子元素在線性方向上(水平方向和垂直方向)依次排列
- 線性布局容器包括 Row] 和 Column 辣之。Column容器內(nèi)子元素按照垂直方向排列,Row容器內(nèi)子元素按照水平方向排列
主軸
- 線性布局容器在布局方向上的軸線皱炉,子元素默認(rèn)沿主軸排列怀估。
- Row容器主軸為橫向,Column容器主軸為縱向。通過justifyContent屬性設(shè)置子元素在容器主軸上的排列方式
- 默認(rèn)相鄰子元素是緊貼著的多搀,也可以通過space設(shè)置子元素間的間距
Column容器內(nèi)子元素在主軸上的排列
主軸方向:垂直向下
Column() {
...
}.justifyContent(FlexAlign.Start)
- justifyContent(FlexAlign.Start):元素在主軸方向首端對齊歧蕉,第一個(gè)元素與行首對齊,同時(shí)后續(xù)的元素與前一個(gè)對齊
- justifyContent(FlexAlign.Center):元素在主軸方向中心對齊康铭,第一個(gè)元素與行首的距離與最后一個(gè)元素與行尾距離相同
- justifyContent(FlexAlign.End):元素在主軸方向尾部對齊廊谓,最后一個(gè)元素與行尾對齊,其他元素與后一個(gè)對齊
- justifyContent(FlexAlign.Spacebetween):主軸方向均勻分配元素麻削,相鄰元素之間距離相同蒸痹。第一個(gè)元素與行首對齊,最后一個(gè)元素與行尾對齊
- justifyContent(FlexAlign.SpaceAround):主軸方向均勻分配元素呛哟,相鄰元素之間距離相同叠荠。第一個(gè)元素到行首的距離和最后一個(gè)元素到行尾的距離是相鄰元素之間距離的一半
- justifyContent(FlexAlign.SpaceEvenly):主軸方向均勻分配元素,相鄰元素之間的距離扫责、第一個(gè)元素與行首的間距榛鼎、最后一個(gè)元素到行尾的間距都完全一樣
Row容器內(nèi)子元素在主軸上的排列
主軸方向:水平向右
Row() {
...
}.justifyContent(FlexAlign.Start)
- justifyContent(FlexAlign.Start):元素在主軸方向首端對齊,第一個(gè)元素與行首對齊鳖孤,同時(shí)后續(xù)的元素與前一個(gè)對齊
- justifyContent(FlexAlign.Center):元素在主軸方向中心對齊者娱,第一個(gè)元素與行首的距離與最后一個(gè)元素與行尾距離相同
- justifyContent(FlexAlign.End):元素在主軸方向尾部對齊,最后一個(gè)元素與行尾對齊苏揣,其他元素與后一個(gè)對齊
- justifyContent(FlexAlign.Spacebetween):主軸方向均勻分配元素黄鳍,相鄰元素之間距離相同。第一個(gè)元素與行首對齊平匈,最后一個(gè)元素與行尾對齊
- justifyContent(FlexAlign.SpaceAround):主軸方向均勻分配元素框沟,相鄰元素之間距離相同。第一個(gè)元素到行首的距離和最后一個(gè)元素到行尾的距離是相鄰元素之間距離的一半
- justifyContent(FlexAlign.SpaceEvenly):主軸方向均勻分配元素增炭,相鄰元素之間的距離忍燥、第一個(gè)元素與行首的間距、最后一個(gè)元素到行尾的間距都完全一樣
交叉軸
- 垂直于主軸方向的軸線隙姿。Row容器交叉軸為縱向梅垄,Column容器交叉軸為橫向。
- 通過alignItems屬性設(shè)置子元素在交叉軸(排列方向的垂直方向)上的對齊方式
- alignSelf屬性用于控制單個(gè)子元素在容器交叉軸上的對齊方式输玷,其優(yōu)先級高于alignItems屬性队丝,如果設(shè)置了alignSelf屬性,則在單個(gè)子元素上會覆蓋alignItems屬性
Column容器內(nèi)子元素在水平方向上的排列
Column() {
...
}.alignItems(HorizontalAlign.Start)
- HorizontalAlign.Start:子元素在水平方向左對齊
- HorizontalAlign.Center:子元素在水平方向居中對齊
- HorizontalAlign.End:子元素在水平方向右對齊饲嗽。
Row容器內(nèi)子元素在垂直方向上的排列
Row() {
...
}.alignItems(VerticalAlign.Top)
- VerticalAlign.Top:子元素在垂直方向頂部對齊
- VerticalAlign.Center:子元素在垂直方向居中對齊
- VerticalAlign.Bottom:子元素在垂直方向底部對齊
層疊布局(Stack)
- 層疊布局主要用于實(shí)現(xiàn)基于Z軸的布局炭玫,容器中的子元素(子組件)依次入棧,后一個(gè)子元素覆蓋前一個(gè)子元素貌虾,子元素可以疊加,也可以通過zIndex設(shè)置位置
- 可以通過 alignContent參數(shù) 實(shí)現(xiàn)位置的相對移動
Stack({ alignContent: Alignment.BottomStart })
彈性布局(Flex)
- Row和Column容器只支持單方向的布局裙犹。你可以把Flex理解為它倆的升級版尽狠,能更靈活的控制布局方向和子元素布局衔憨。
- 可以設(shè)置布局方向,是否自動換行等
彈性布局方向圖
Flex({ direction: FlexDirection.Row })
- FlexDirection.Row(默認(rèn)值):主軸為水平方向袄膏,子組件從起始端沿著水平方向開始排布
- FlexDirection.RowReverse:主軸為水平方向践图,子組件從終點(diǎn)端沿著FlexDirection. Row相反的方向開始排布
- FlexDirection.Column:主軸為垂直方向,子組件從起始端沿著垂直方向開始排布
- FlexDirection.ColumnReverse:主軸為垂直方向沉馆,子組件從終點(diǎn)端沿著FlexDirection. Column相反的方向開始排布
主軸為水平方向的Flex容器示意圖
主軸對齊方式
通過justifyContent參數(shù)設(shè)置在主軸方向的對齊方式码党,和Row、Column的主軸對齊方式行為一樣
交叉軸對齊方式
可以通過Flex組件的alignItems參數(shù)設(shè)置子組件在交叉軸的對齊方式斥黑,子組件默認(rèn)使用Flex組件的對齊方式揖盘。但也可以通過alignSelf單獨(dú)設(shè)置對齊方式
Flex({ alignItems: ItemAlign.Start })
ItemAlign.Auto:使用Flex容器中默認(rèn)配置。
ItemAlign.Start:交叉軸方向首部對齊
ItemAlign.Center:交叉軸方向居中對齊
ItemAlign.End:交叉軸方向底部對齊
子組件通過 alignSelf 設(shè)置在父容器交叉軸的對齊格式锌奴,覆蓋Flex布局容器中alignItems配置
相對布局(RelativeContainer)
- 相對布局可以讓子元素指定兄弟元素或父容器作為錨點(diǎn)兽狭,基于錨點(diǎn)做位置布局
- 必須為RelativeContainer及其子元素設(shè)置ID,用于指定錨點(diǎn)信息鹿蜀。未設(shè)置ID的子元素不會顯示
- RelativeContainer ID為“container”箕慧,其余子元素的ID通過id屬性設(shè)置。
- 子元素通過
alignRules
指定相對布局規(guī)則
錨點(diǎn)的對齊位置示意圖
一個(gè)示例
@Entry
@Component
struct Index {
build() {
Row() {
RelativeContainer() {
Row()
.width(100)
.height(100)
.backgroundColor('#FF3333')
.alignRules({
top: { anchor: '__container__', align: VerticalAlign.Top }, //以父容器為錨點(diǎn)茴恰,豎直方向頂頭對齊
middle: { anchor: '__container__', align: HorizontalAlign.Center } //以父容器為錨點(diǎn)颠焦,水平方向居中對齊
})
.id('row1') //設(shè)置錨點(diǎn)為row1
Row() {
Image($r('app.media.icon'))
}
.height(100).width(100)
.alignRules({
top: { anchor: 'row1', align: VerticalAlign.Bottom }, //以row1組件為錨點(diǎn),豎直方向低端對齊
left: { anchor: 'row1', align: HorizontalAlign.Start } //以row1組件為錨點(diǎn)往枣,水平方向開頭對齊
})
.id('row2') //設(shè)置錨點(diǎn)為row2
Row()
.width(100)
.height(100)
.backgroundColor('#FFCC00')
.alignRules({
top: { anchor: 'row2', align: VerticalAlign.Top }
})
.id('row3') //設(shè)置錨點(diǎn)為row3
Row()
.width(100)
.height(100)
.backgroundColor('#FF9966')
.alignRules({
top: { anchor: 'row2', align: VerticalAlign.Top },
left: { anchor: 'row2', align: HorizontalAlign.End },
})
.id('row4') //設(shè)置錨點(diǎn)為row4
Row()
.width(100)
.height(100)
.backgroundColor('#FF66FF')
.alignRules({
top: { anchor: 'row2', align: VerticalAlign.Bottom },
middle: { anchor: 'row2', align: HorizontalAlign.Center }
})
.id('row5') //設(shè)置錨點(diǎn)為row5
}
.width(300).height(300)
.border({ width: 2, color: '#6699FF' })
}
.height('100%').margin({ left: 30 })
}
}
創(chuàng)建列表(List)
- 列表容器是為了高效處理長列表的容器蒸健,能支持橫向、豎向滾動婉商,數(shù)據(jù)分組似忧,分組頭懸浮等功能
- 列表容器內(nèi)的所有子元素必須是 ListItemGroup 或ListItem,我們實(shí)際的內(nèi)容是在這倆容器內(nèi)部的
- 創(chuàng)建列表子元素一般使用 ForEach 來減少開發(fā)量
List丈秩、ListItemGroup和ListItem組件關(guān)系
List() {
ListItem() {
}
ListItem() {
}
ListItemGroup() {
}
LazyForEach(this.dataSource, item => {
ListItem() {
...
}
})
}
// 設(shè)置垂直方向
.listDirection(Axis.Vertical)
// 粘性header
.sticky(StickyStyle.Header)
// 兩列
.lanes(2)
創(chuàng)建網(wǎng)格(Grid/GridItem)
- 網(wǎng)格布局主要用于處理固定行列的UI盯捌,也支持動態(tài)調(diào)整。很類似iOS中的UICollectionView蘑秽。
- Grid 容器的子組件一定是 GridItem
Grid饺著,GridItem關(guān)系
容器內(nèi)每一個(gè)條目對應(yīng)一個(gè)GridItem組件
行列數(shù)量可配
- Grid組件提供了rowsTemplate和columnsTemplate屬性用于設(shè)置網(wǎng)格布局行列數(shù)量與尺寸占比。
- rowsTemplate和columnsTemplate屬性值是一個(gè)由多個(gè)空格和'數(shù)字+fr'間隔拼接的字符串肠牲,fr的個(gè)數(shù)即網(wǎng)格布局的行或列數(shù)幼衰,fr前面的數(shù)值大小,用于計(jì)算該行或列在網(wǎng)格布局寬度上的占比缀雳,最終決定該行或列的寬度
Grid() {
...
}
.rowsTemplate('1fr 1fr 1fr')
.columnsTemplate('1fr 2fr 1fr')
單個(gè)網(wǎng)格可以橫跨多行或多列
通過設(shè)置GridItem的rowStart渡嚣、rowEnd、columnStart和columnEnd可以實(shí)現(xiàn)單個(gè)網(wǎng)格橫跨多行或多列的場景
Grid() {
GridItem() {}
GridItem() {}
GridItem() {}
.columnStart(1)
.columnEnd(2)
GridItem() {}
.rowStart(1)
.rowEnd(2)
GridItem() {}
GridItem() {}
GridItem() {}
GridItem() {}
.columnStart(1)
.columnEnd(3)
}
.rowsTemplate('1fr 1fr 1fr')
.columnsTemplate('1fr 1fr 1fr 1fr')
.columnsGap(8)
.rowsGap(8)
其他常用布局容器和組件
- 創(chuàng)建輪播(Swiper)實(shí)現(xiàn)輪播圖功能
- 柵格布局(GridRow/GridCol)和Grid布局類似,但是可以根據(jù)設(shè)置的分割點(diǎn)動態(tài)顯示列數(shù)识椰。特別適合做多設(shè)備適配布局
- Badge 實(shí)現(xiàn)消息小紅點(diǎn)和消息數(shù)功能
- WaterFlow 實(shí)現(xiàn)瀑布流功能
- Video 實(shí)現(xiàn)視頻播放功能
- TextTimer 實(shí)現(xiàn)倒計(jì)時(shí)顯示功能
- DataPanel 數(shù)據(jù)面板組件绝葡,使用占比圖展示多個(gè)數(shù)據(jù)的占比情況
- Gauge 以環(huán)形圖表形式展示數(shù)據(jù)
Marquee 走馬燈效果
PatternLock 圖形密碼鎖組件
- Rating 評分組件
- Stepper 步驟導(dǎo)航器組件,主要用于引導(dǎo)介紹功能