固定底部 布局_Google Flutter 布局(四)-Baseline IntrinsicWidth详解
1.1 簡(jiǎn)介
Baseline這個(gè)控件,做過移動(dòng)端開發(fā)的都會(huì)了解過,一般文字排版的時(shí)候,可能會(huì)用到它。它的作用很簡(jiǎn)單,根據(jù)child的baseline,來(lái)調(diào)整child的位置。例如兩個(gè)字號(hào)不一樣的文字,希望底部在一條水平線上,就可以使用這個(gè)控件,是一個(gè)非常基礎(chǔ)的控件。
關(guān)于字符的Baseline,可以看下下面這張圖,這具體就涉及到了字體排版,感興趣的同學(xué)可以自行了解。
1.2 布局行為
Baseline控件布局行為分為兩種情況:
- 如果child有baseline,則根據(jù)child的baseline屬性,調(diào)整child的位置;
- 如果child沒有baseline,則根據(jù)child的bottom,來(lái)調(diào)整child的位置。
1.3 繼承關(guān)系
Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > Baseline1.4 示例代碼
new Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ new Baseline( baseline: 50.0, baselineType: TextBaseline.alphabetic, child: new Text( 'TjTjTj', style: new TextStyle( fontSize: 20.0, textBaseline: TextBaseline.alphabetic, ), ), ), new Baseline( baseline: 50.0, baselineType: TextBaseline.alphabetic, child: new Container( width: 30.0, height: 30.0, color: Colors.red, ), ), new Baseline( baseline: 50.0, baselineType: TextBaseline.alphabetic, child: new Text( 'RyRyRy', style: new TextStyle( fontSize: 35.0, textBaseline: TextBaseline.alphabetic, ), ), ), ],)上述運(yùn)行結(jié)果是左右兩個(gè)文本跟中間的Container底部在一個(gè)水平線上,這也印證了Baseline的布局行為。
1.5 源碼解析
const Baseline({ Key key, @required this.baseline, @required this.baselineType, Widget child})1.5.1 屬性解析
baseline:baseline數(shù)值,必須要有,從頂部算。
baselineType:bseline類型,也是必須要有的,目前有兩種類型:
- alphabetic:對(duì)齊字符底部的水平線;
- ideographic:對(duì)齊表意字符的水平線。
1.5.2 源碼
我們來(lái)看看源碼中具體計(jì)算尺寸的這段代碼
child.layout(constraints.loosen(), parentUsesSize: true);final double childBaseline = child.getDistanceToBaseline(baselineType);final double actualBaseline = baseline;final double top = actualBaseline - childBaseline;final BoxParentData childParentData = child.parentData;childParentData.offset = new Offset(0.0, top);final Size childSize = child.size;size = constraints.constrain(new Size(childSize.width, top + childSize.height));getDistanceToBaseline這個(gè)函數(shù)是獲取baseline數(shù)值的,存在的話,就取這個(gè)值,不存在的話,則取其高度。
整體的計(jì)算過程:
1.6 使用場(chǎng)景
跟字符對(duì)齊相關(guān)的會(huì)用到,其他場(chǎng)景暫時(shí)沒有想到。
2. FractionallySizedBox
A widget that sizes its child to a fraction of the total available space
2.1 簡(jiǎn)介
FractionallySizedBox控件會(huì)根據(jù)現(xiàn)有空間,來(lái)調(diào)整child的尺寸,所以說child就算設(shè)置了具體的尺寸數(shù)值,也不起作用。
2.2 布局行為
FractionallySizedBox的布局行為主要跟它的寬高因子兩個(gè)參數(shù)有關(guān),當(dāng)參數(shù)為null或者有具體數(shù)值的時(shí)候,布局表現(xiàn)不一樣。當(dāng)然,還有一個(gè)輔助參數(shù)alignment,作為對(duì)齊方式進(jìn)行布局。
- 當(dāng)設(shè)置了具體的寬高因子,具體的寬高則根據(jù)現(xiàn)有空間寬高 * 因子,有可能會(huì)超出父控件的范圍,當(dāng)寬高因子大于1的時(shí)候;
- 當(dāng)沒有設(shè)置寬高因子,則填滿可用區(qū)域;
2.3 繼承關(guān)系
Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > FractionallySizedBox2.4 示例代碼
new Container( color: Colors.blue, height: 150.0, width: 150.0, padding: const EdgeInsets.all(10.0), child: new FractionallySizedBox( alignment: Alignment.topLeft, widthFactor: 1.5, heightFactor: 0.5, child: new Container( color: Colors.red, ), ), )運(yùn)行效果如下所示
2.5 源碼解析
const FractionallySizedBox({ Key key, this.alignment = Alignment.center, this.widthFactor, this.heightFactor, Widget child,})2.5.1 屬性解析
alignment:對(duì)齊方式,不能為null。
widthFactor:寬度因子,跟之前介紹的控件類似,寬度乘以這個(gè)值,就是最后的寬度。
heightFactor:高度因子,用作計(jì)算最后實(shí)際高度的。
其中widthFactor和heightFactor都有一個(gè)規(guī)則
- 如果不為null,那么實(shí)際的最大寬高度則為child的寬高乘以這個(gè)因子;
- 如果為null,那么child的寬高則會(huì)盡量充滿整個(gè)區(qū)域。
2.5.2 源碼
FractionallySizedBox內(nèi)部具體渲染是由RenderFractionallySizedOverflowBox來(lái)實(shí)現(xiàn)的,通過命名就可以看出,這個(gè)控件可能會(huì)Overflow。
我們直接看實(shí)際計(jì)算尺寸的代碼
double minWidth = constraints.minWidth;double maxWidth = constraints.maxWidth;if (_widthFactor != null) { final double width = maxWidth * _widthFactor; minWidth = width; maxWidth = width;}double minHeight = constraints.minHeight;double maxHeight = constraints.maxHeight;if (_heightFactor != null) { final double height = maxHeight * _heightFactor; minHeight = height; maxHeight = height;}源代碼中,根據(jù)寬高因子是否存在,來(lái)進(jìn)行相對(duì)應(yīng)的尺寸計(jì)算。這個(gè)過程非常簡(jiǎn)單,不再贅述。
2.6 使用場(chǎng)景
當(dāng)需要在一個(gè)區(qū)域里面取百分比尺寸的時(shí)候,可以使用這個(gè),比方說,高度40%寬度70%的區(qū)域。當(dāng)然,AspectRatio也可以達(dá)到近似的效果。
3. IntrinsicHeight
A widget that sizes its child to the child's intrinsic height.
3.1 簡(jiǎn)介
IntrinsicHeight的作用是調(diào)整child到固定的高度。這個(gè)控件筆者也是看了很久,不知道它的作用是什么,官方說這個(gè)很有用,但是應(yīng)該盡量少用,因?yàn)槠湫蕟栴}。
3.2 布局行為
這個(gè)控件的作用,是將可能高度不受限制的child,調(diào)整到一個(gè)合適并且合理的尺寸。
3.3 繼承關(guān)系
Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > IntrinsicHeight3.4 示例代碼
new IntrinsicHeight( child: new Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ new Container(color: Colors.blue, width: 100.0), new Container(color: Colors.red, width: 50.0,height: 50.0,), new Container(color: Colors.yellow, width: 150.0), ], ),);當(dāng)沒有IntrinsicHeight包裹著,可以看到,第一三個(gè)Container高度是不受限制的,當(dāng)外層套一個(gè)IntrinsicHeight,第一三個(gè)Container高度就調(diào)整到第二個(gè)一樣的高度。
3.5 源碼解析
構(gòu)造函數(shù)如下:
const IntrinsicHeight({ Key key, Widget child })3.5.1 屬性解析
除了child,沒有提供額外的屬性。
3.5.2 源碼
當(dāng)child不為null的時(shí)候,具體的布局代碼如下:
BoxConstraints childConstraints = constraints;if (!childConstraints.hasTightHeight) { final double height = child.getMaxIntrinsicHeight(childConstraints.maxWidth); assert(height.isFinite); childConstraints = childConstraints.tighten(height: height);}child.layout(childConstraints, parentUsesSize: true);size = child.size;首先會(huì)檢測(cè)是否只有一個(gè)高度值滿足約束條件,如果不是的話,則返回一個(gè)最小的高度。然后調(diào)整尺寸。
3.6 使用場(chǎng)景
說老實(shí)話,不知道在什么場(chǎng)景使用,可以替代的控件也有的。谷歌說很有用,效率會(huì)有問題,建議一般的就別用了。
4. IntrinsicWidth
A widget that sizes its child to the child's intrinsic width.
4.1 簡(jiǎn)介
IntrinsicWidth從描述看,跟IntrinsicHeight類似,一個(gè)是調(diào)整高度,一個(gè)是調(diào)整寬度。同樣是會(huì)存在效率問題,能別使用就盡量別使用。
4.2 布局行為
IntrinsicWidth不同于IntrinsicHeight,它包含了額外的兩個(gè)參數(shù),stepHeight以及stepWidth。而IntrinsicWidth的布局行為跟這兩個(gè)參數(shù)相關(guān)。
- 當(dāng)stepWidth不是null的時(shí)候,child的寬度將會(huì)是stepWidth的倍數(shù),當(dāng)stepWidth值比child最小寬度小的時(shí)候,這個(gè)值不起作用;
- 當(dāng)stepWidth為null的時(shí)候,child的寬度是child的最小寬度;
- 當(dāng)stepHeight不為null的時(shí)候,效果跟stepWidth相同;
- 當(dāng)stepHeight為null的時(shí)候,高度取最大高度。
4.3 繼承關(guān)系
Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > IntrinsicWidth4.4 示例代碼
new Container( color: Colors.green, padding: const EdgeInsets.all(5.0), child: new IntrinsicWidth( stepHeight: 450.0, stepWidth: 300.0, child: new Column( children: [ new Container(color: Colors.blue, height: 100.0), new Container(color: Colors.red, width: 150.0, height: 100.0), new Container(color: Colors.yellow, height: 150.0,), ], ), ),)分別對(duì)stepWidth以及stepHeight設(shè)置不同的值,可以看到不同的效果,當(dāng)step值比最小寬高小的時(shí)候,這個(gè)值其實(shí)是不起作用的。感興趣的同學(xué)可以自己試試。
4.5 源碼解析
構(gòu)造函數(shù)
const IntrinsicWidth({ Key key, this.stepWidth, this.stepHeight, Widget child })4.5.1 屬性解析
stepWidth:可以為null,效果參看上面所說的布局行為。
stepHeight:可以為null,效果參看上面所說的布局行為。
4.5.2 源碼
我們先來(lái)看看布局代碼中_applyStep函數(shù)
static double _applyStep(double input, double step) {assert(input.isFinite);if (step == null) return input;return (input / step).ceil() * step;}如果存在step數(shù)值的話,則會(huì)是step的倍數(shù),如果step為null,則返回原始的尺寸。
接下來(lái)我們看看child不為null時(shí)候的布局代碼
BoxConstraints childConstraints = constraints;if (!childConstraints.hasTightWidth) { final double width = child.getMaxIntrinsicWidth(childConstraints.maxHeight); assert(width.isFinite); childConstraints = childConstraints.tighten(width: _applyStep(width, _stepWidth));}if (_stepHeight != null) { final double height = child.getMaxIntrinsicHeight(childConstraints.maxWidth); assert(height.isFinite); childConstraints = childConstraints.tighten(height: _applyStep(height, _stepHeight));}child.layout(childConstraints, parentUsesSize: true);size = child.size;寬度方面的布局跟IntrinsicHeight高度部分相似,只是多了一個(gè)step的額外數(shù)值。總體的布局表現(xiàn)跟上面分析的布局行為一致,根據(jù)step值是否是null來(lái)進(jìn)行判斷,但是注意其對(duì)待高度與寬度的表現(xiàn)略有差異。
4.6 使用場(chǎng)景
這個(gè)控件,說老實(shí)話,筆者還是不知道該在什么場(chǎng)景下使用,可能會(huì)有些特殊的場(chǎng)景。但是從IntrinsicWidth與IntrinsicHeight布局差異看,Flutter基礎(chǔ)控件封的確實(shí)很隨性,一些可有可無(wú)甚至是重復(fù)的控件,我覺得精簡(jiǎn)精簡(jiǎn)挺好的,哈哈。
總結(jié)
以上是生活随笔為你收集整理的固定底部 布局_Google Flutter 布局(四)-Baseline IntrinsicWidth详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: QQ阅读怎么写小说?
- 下一篇: oracle 子表数据变化时主表也会更新
