Flutter七日遊第三天:2018-12-18 天氣:晴朗
浪了兩天,Dart語法基本上熟悉了,繪圖也不怕了,如今進入正軌,繼續浪~
今天來學些枯燥的東西了--基礎控件,戒驕戒躁,基礎仍是要好好掌握。
本文目的在於儘量看清控件的全局(細枝末節點到爲止),詳細用法等佈局實戰再細說吧
本文能用圖的,儘可能不用字(看完你可能會以爲我腦洞有點大),廢話很少說,進入今天的內容css
Widget:[小器具,裝飾品,窗口小部件],之後簡稱:
控件
下面看一下Widget樹:(只延伸到下代)html
StatelessWidget
和StatefulWidget
目前出如今我眼前的只這有兩個,因此先只看這兩個:git
StatelessWidget:源碼第一句話:
---->A widget that does not require mutable state.
---->一個不須要變更狀態的控件
StatefulWidget :源碼第一句話:
---->A widget that has mutable state.
---->一個可變更狀態的控件
複製代碼
-------->[構造方法,須要一個key,並且老爸已經給他了]----
/// Initializes [key] for subclasses.
const StatelessWidget({ Key key }) : super(key: key);
-------->[createElement方法複寫Widget方法,使用StatelessElement--tag1--自給自足]
/// It is uncommon for subclasses to override this method.
//子類重寫此方法是不常見的。----因此就不要沒事找事了
StatelessElement createElement() => StatelessElement(this);
--tag1-->[StatelessElement,接收一個StatelessWidget]
/// An [Element] that uses a [StatelessWidget] as its configuration.
class StatelessElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration.
StatelessElement(StatelessWidget widget) : super(widget);
-------->[使用如今要關注的只有:build方法--]
/// Describes the part of the user interface represented by this widget.
//描述此控件呈如今用戶界面上的部分
@protected
Widget build(BuildContext context);//空實現
複製代碼
StatelessWidget
:
StatelessWidget
映入眼簾,可見該類內部必定有一個build方法返回一個Widgetgithub
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.lightBlue,
),
home:MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
//不難看出MaterialApp是一個Widget,並且至少有title,theme,home三個屬性
並且home傳入的是一個Widget
複製代碼
Widget源碼偷窺者
, 成就獎勵:三張卡片:卡片初始屬性:見白框(PS:
屬性會隨着你的閱歷變多哦
)編程
- | - | - |
---|---|---|
接下來會列出一長串屬性,並挑選些簡單的屬性測試一下
若是你以爲及其無聊,列屬性的地方能夠跳過,基本上每三個作一個小測試canvas
MaterialApp--材料App
An application that uses material design.
源碼如是說:一個使用材料設計的App
繼承自StatefulWidget
,字段蠻多的,先列一下,看看如今用到的,其餘的用到再說吧。數組
class MaterialApp extends StatefulWidget
this.navigatorKey,
this.home,//--->tag1<---
this.routes = const <String, WidgetBuilder>{},
this.initialRoute,
this.onGenerateRoute,
this.onUnknownRoute,
this.navigatorObservers = const <NavigatorObserver>[],
this.builder,
this.title = '',//--->tag2<---
this.onGenerateTitle,
this.color,
this.theme,//--->tag3<---
this.locale,
this.localizationsDelegates,
this.localeListResolutionCallback,
this.localeResolutionCallback,
this.supportedLocales = const <Locale>[Locale('en', 'US')],
this.debugShowMaterialGrid = false,
this.showPerformanceOverlay = false,
this.checkerboardRasterCacheImages = false,
this.checkerboardOffscreenLayers = false,
this.showSemanticsDebugger = false,
this.debugShowCheckedModeBanner = true,
//--->tag1<---[title是個字符串]----
/// This value is passed unmodified to [WidgetsApp.title].
final String title;
//--->tag2<---[theme是個ThemeData對象:保存材料設計主題的顏色和版式值]----
/// The colors to use for the application's widgets. final ThemeData theme; //--->tag3<---[home是個Widget對象]---- /// {@macro flutter.widgets.widgetsApp.home} final Widget home; 複製代碼
Scaffold--腳手架
什麼是腳手架,大概就是這個感受吧,也就是輔助腳手的工具,方便施工bash
PreferredSizeWidget this.appBar,
Widget this.body,
Widget this.floatingActionButton,
FloatingActionButtonLocation this.floatingActionButtonLocation,
FloatingActionButtonAnimator this.floatingActionButtonAnimator,
List<Widget> this.persistentFooterButtons,
Widget this.drawer,
Widget this.endDrawer,
Widget this.bottomNavigationBar,
Widget this.bottomSheet,
Color this.backgroundColor,
bool this.resizeToAvoidBottomPadding = true,
bool this.primary = true,
複製代碼
AppBar--App的Bar
就像安卓的ToolBar同樣的控件微信
Widget this.leading,
bool this.automaticallyImplyLeading = true,
Widget this.title,
List<Widget> this.actions,
Widget this.flexibleSpace,
PreferredSizeWidget this.bottom,
double this.elevation = 4.0,
Color this.backgroundColor,
Brightness this.brightness,
IconThemeData this.iconTheme,
TextTheme this.textTheme,
bool this.primary = true,
bool this.centerTitle,
double this.titleSpacing = NavigationToolbar.kMiddleSpacing,
double this.toolbarOpacity = 1.0,
double this.bottomOpacity = 1.0,
複製代碼
能力小測試
:MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.lightBlue,
),
home: Scaffold(
appBar: AppBar(
title: Text("張風捷特烈"),//標題
backgroundColor: Color(0xffcbf231), //背景色
elevation: 12,//陰影
centerTitle: true,
toolbarOpacity: .4)//透明度
));
複製代碼
歡迎繼續冒險
- | - | - |
---|---|---|
Text--文字
const Text(this.data, {
TextStyle this.style,
TextAlign this.textAlign,
TextDirection this.textDirection,
Locale this.locale,
bool this.softWrap,
TextOverflow this.overflow,
double this.textScaleFactor,
int this.maxLines,
String this.semanticsLabel,
/// Creates a text widget with a [TextSpan].
const Text.rich(this.textSpan, {
//同上
})
複製代碼
//---->[TextStyle]----------------
bool this.inherit = true,
Color this.color,
double this.fontSize,
FontWeight this.fontWeight,
FontStyle this.fontStyle,
double this.letterSpacing,
double this.wordSpacing,
TextBaseline this.textBaseline,
double this.height,
Locale this.locale,
Paint this.foreground,
Paint this.background,
List<ui.Shadow> this.shadows,
TextDecoration this.decoration,
Color this.decorationColor,
TextDecorationStyle this.decorationStyle,
String this.debugLabel,
String String fontFamily,
//---->[TextAlign]----------------
enum TextAlign {
left,right,center,justify,start,end,
}
//---->[TextOverflow]----------------
enum TextOverflow {
clip,fade,ellipsis,
}
複製代碼
FloatingActionButton--浮動動做按鈕
Widget this.child,
String this.tooltip,
Color this.foregroundColor,
Color this.backgroundColor,
Object this.heroTag = const _DefaultHeroTag(),
double this.elevation = 6.0,
double this.highlightElevation = 12.0,
VoidCallback @required this.onPressed,
bool this.mini = false,
ShapeBorder this.shape = const CircleBorder(),
Clip this.clipBehavior = Clip.none,
MaterialTapTargetSize this.materialTapTargetSize,
bool this.isExtended = false,
複製代碼
Icon--圖標
double this.size,
Color this.color,
String this.semanticLabel,------This label does not show in the UI.
TextDirection this.textDirection,
複製代碼
body: Text(
"一簫一劍生平意,負盡狂名十五年",
maxLines: 1,
overflow: TextOverflow.fade,
style: TextStyle(
color: Colors.blue,
fontSize: 20,
letterSpacing: 10,
fontWeight: FontWeight.bold,
background: Paint()..color = Colors.amberAccent),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.deepOrangeAccent,
elevation: 12,
highlightElevation: 24,
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add,size: 40,color: Colors.white,semanticLabel:"toly"),
),
複製代碼
以上6張卡片是初始項目中的控件,經過新手任務基本上更加熟悉了一些
Flutter還有哪些控件,建議看一下Flutter中文網,羅列的挺好的,下面一塊兒學習一下
(PS:看了一下,真是多如雞毛...嚇得我不知從何入手)app
所謂`打蛇打七寸,擒賊先擒王`,小兵以後再收拾
經過Android和html+css,我領悟到,對於界面設計者而言,佈局是相當重要的,因此先看容器
複製代碼
Layout
佈局容器之Row+Column--行+列
---->[源碼註釋第一句]-----------------------------
A widget that displays its children in a horizontal array.
一個以水平數組的形式顯示其子部件的Widget。
Row({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
List<Widget> children = const <Widget>[],
複製代碼
children看來是一個Widget數組,想一想也不難理解,畢竟作大哥的,固然要有很多小弟啦
注:爲了方便修改,如下代碼把Scaffold的body屬性值抽成變量使用
var row_test = Row(
children: <Widget>[
Text('絕域從軍計惘然,,'),
Text('東南幽恨滿詞箋。'),
Text('一簫一劍生平意,'),
Text('負盡狂名十五年。'),
],
);
複製代碼
能夠看出越界有提醒,感受蠻有心的,水平排列沒毛病
---->[源碼註釋第一句]-----------------------------
A widget that displays its children in a vertical array.
一個以豎直數組的形式顯示其子部件的Widget。
Column({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
List<Widget> children = const <Widget>[],
複製代碼
var row_column = Column(
children: <Widget>[
Text('絕域從軍計惘然,,'),
Text('東南幽恨滿詞箋。'),
Text('一簫一劍生平意,'),
Text('負盡狂名十五年。'),
],
);
複製代碼
佈局菜鳥
---獎勵卡片:- | - | - |
---|---|---|
恭喜解鎖新卡片:Expanded,快去用用吧
Expanded意思是:使…伸展
,看到下面的圖,你應該就會明白
var row_test = Row(
children: <Widget>[
Expanded(
child:Text('絕域從軍計惘然,'),
),
Expanded(
child:Text('東南幽恨滿詞箋。'),
),
Expanded(
child:Text('一簫一劍生平意,'),
),
Expanded(
child:Text('負盡狂名十五年。'),
),
],
);
複製代碼
Container--容器
能夠理解爲Android中的View,更像html中的div
Container是一個沒有狀態的控件
---->[源碼註釋第一句]-----------------------------
A convenience widget that combines common painting, positioning, and sizing widgets.
一個方便的widget,它組合了常見的painting、positioning和sizing 控件。
Color color,
double width,
double height,
Widget this.child,
EdgeInsetsGeometry this.margin,
EdgeInsetsGeometry this.padding,
AlignmentGeometry this.alignment,
Decoration Decoration decoration,
Decoration this.foregroundDecoration,
BoxConstraints BoxConstraints constraints,
Matrix4 this.transform,
複製代碼
[插曲]這裏分享一個點:
當看到一個新的東西應該怎麼辦?
好比`margin`,看到`EdgeInsetsGeometry`個人心情是一臉懵X,不該該是數字嗎?
進源碼:`abstract class EdgeInsetsGeometry {`,抽象的,找他兒子去,
AndroidStudio中按`Ctrl+H`能夠查看繼承樹,而後就看到了EdgeInsets.fromLTRB
這樣Flutter的margin就和你的知識庫中的margin進行了鏈接,你就會用了
class EdgeInsets extends EdgeInsetsGeometry {
const EdgeInsets.fromLTRB(this.left, this.top, this.right, this.bottom);
const EdgeInsets.all(double value)
: left = value, top = value, right = value, bottom = value;
新事物每每都與舊事物有聯繫,學習新事物最好快速找到它與你知識庫中舊事物的聯繫,
聯繫的多少取決於你知識庫中內容的多少,鏈接得越多,你會越快或越能掌握舊事物
複製代碼
var container_test = Container(
color: Color.fromARGB(100, 81, 211, 253),
height: 100,
width: 200,
child: Text("張風捷特烈"),
margin: EdgeInsets.fromLTRB(5, 10, 15, 20),
padding: EdgeInsets.all(40),
);
複製代碼
padding和margin簡稱pm,左圖是上面代碼沒有pm時,右圖是有pm時
Container使用者
--卡牌獎勵:- | - | - |
---|---|---|
NPC:恭喜解鎖兩張輔助卡
Padding
和Center
,快來測試一下吧
這兩個沒什麼好說的,顧圖思義,看圖吧
var padding_test = Container(
color: Color.fromARGB(100, 81, 211, 253),
height: 150,
width: 250,
child: Padding(
padding: EdgeInsets.all(10),
child: Text("張風捷特烈"),
),
);
var center_test = Container(
color: Color.fromARGB(100, 81, 211, 253),
height: 150,
width: 250,
child: Center(
child: Text("張風捷特烈"),
),
);
複製代碼
Stack -- 堆疊
第一反應:棧?有道了一下,有堆疊的意思
---->[源碼註釋第一句]-----------------------------
A widget that positions its children relative to the edges of its box.
一個相對於它的框的邊緣來定位它的子部件的Widget。
this.alignment = AlignmentDirectional.topStart,
this.textDirection,
this.fit = StackFit.loose,
this.overflow = Overflow.clip,
List<Widget> children = const <Widget>[],
複製代碼
- | - | - |
---|---|---|
請完成下面佈局:
var stack_test = Container(
color: Color.fromARGB(100, 81, 211, 253),
height: 150,
width: 250,
child: Stack(
alignment: Alignment.centerLeft,
children: <Widget>[
Text('絕域從軍計惘然,,'),
Align(
alignment: Alignment.topRight,
widthFactor: 1.5,
child: Card(
elevation: 10, color: Color(0xffffffff), child: Text('東南幽恨滿詞箋。')),
),
Text('一簫一劍生平意,'),
Text('負盡狂名十五年。'),
],
));
複製代碼
如今對Stack有點感受了吧,它像FramLayout同樣會疊合控件,
而且alignment還能夠肯定Stack自身相對於老爸的位置
Align也有alignment,不過能有一個孩子,Card我最喜歡了
這裏mark一下Card裏的ShapeBorder shape
,源碼粗略看了一下,可能挺好玩,今天主看控件
IndexedStack--定索引顯示
按照索引來顯示堆疊容器中的控件,挺好玩的
var index_stack_test = Container(
color: Color.fromARGB(100, 81, 211, 253),
height: 150,
width: 250,
child: IndexedStack(
index:3,
alignment: Alignment.centerLeft,
children: <Widget>[
Text('絕域從軍計惘然,'),
Align(
alignment: Alignment.topRight,
widthFactor: 1.5,
child: Card(
elevation: 10, color: Color(0xffffffff), child: Text('東南幽恨滿詞箋。')),
),
Text('一簫一劍生平意,'),
Text('負盡狂名十五年。'),
],
));
複製代碼
Transform--變換
transform屬性的Matrix4有機會確定好好分析分析,mark一下
Matrix4.rotationZ傳入的是弧度制的度數,佩服佩服
Transform(
origin: Offset(0, 150),
transform: Matrix4.rotationZ(3.1415 / 4),
child: //同上面的Container,挺長的,不貼了
)
複製代碼
Offstage--顯隱控制
把
負盡狂名十五年
用Offstage包裹一下,offstage爲true--隱藏,爲false--顯示
感受應該挺好用,簡潔,明瞭,人狠話很少。
Offstage(
offstage: false,
child: Text('負盡狂名十五年。'),
),
複製代碼
佈局小新手
:獎勵卡牌:- | - | - |
---|---|---|
隱藏劇情觸發:
NPC:傳說有三條惡龍盤踞在佈局深處,爲禍人間,勇士們,準備好了嗎?
this.children = const <TableRow>[],
this.columnWidths,
this.defaultColumnWidth = const FlexColumnWidth(1.0),
this.textDirection,
this.border,
this.defaultVerticalAlignment = TableCellVerticalAlignment.top,
this.textBaseline,
複製代碼
代碼實現:
columnWidths
:能夠指定每列的寬度
border
:邊線的樣式
children
:經過TableRow
來顯示一行
var table_test = Table(
columnWidths: const <int, TableColumnWidth>{
0: FixedColumnWidth(60.0),
1: FixedColumnWidth(100.0),
2: FixedColumnWidth(100.0),
3: FixedColumnWidth(80.0),
},
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
border:
TableBorder.all(color: Color(0xff16DAF1), width: 1.0, style: BorderStyle.solid),
children: const <TableRow>[
TableRow(
children: <Widget>[
Center(child: Text('姓名')),
Center(child: Text('年齡')),
Center(child: Text('稱號')),
Center(child: Text('武器')),
],
),
TableRow(
children: <Widget>[
Text('捷特'),
Text('24'),
Text('風神'),
Text('黑風劍'),
],
),
TableRow(
children: <Widget>[
Text('巫纓'),
Text('23'),
Text('百里巫纓'),
Text('百里弓'),
],
),
TableRow(
children: <Widget>[
Text('龍少'),
Text('23'),
Text('控尊'),
Text('控尊戒'),
],
),
],
);
複製代碼
屬性很簡潔,可是:FlowDelegate夠熬一碗粥的
FlowDelegate @required this.delegate,
List<Widget> children = const <Widget>[],
複製代碼
簡單分析一下:隨機顏色,隨機長度,到尾部不夠就換行
代碼實現:從網上找了一個
FlowDelegate
的實現類
核心就是根據位置能夠本身繪製孩子的位置(吐槽:源碼了居然沒有實現類,給一個也好啊...)
class MarginFlowDelegate extends FlowDelegate {
EdgeInsets _margin = EdgeInsets.zero;//成員變量_margin
MarginFlowDelegate(this._margin); //構造函數
@override//繪製孩子的方法
void paintChildren(FlowPaintingContext context) {
var offsetX = _margin.left;
var offsetY = _margin.top;
for (int i = 0; i < context.childCount; i++) {
var w = context.getChildSize(i).width + offsetX + _margin.right;
if (w < context.size.width) {
context.paintChild(i, transform: new Matrix4.translationValues(offsetX, offsetY, 0.0));
offsetX = w + _margin.left;
} else {
offsetX = _margin.left;
offsetY += context.getChildSize(i).height + _margin.top + _margin.bottom;
context.paintChild(i,transform: new Matrix4.translationValues(offsetX, offsetY, 0.0));
offsetX += context.getChildSize(i).width + _margin.left + _margin.right;
}
}
}
複製代碼
動態生成Widget數組(可別傻傻的cv,60個Container)
formColorList(int count) {
var random = new Random();
var li = <Widget>[];
for (int i = 0; i < count; i++) {
li.add(new Container(
width: 100 * (random.nextDouble() + 0.3),
height: 30,
color: randomRGB(),
));
}
return li;
}
複製代碼
用起來卻是簡單:
var flow_test = Flow(
delegate: MarginFlowDelegate(EdgeInsets.all(5)),
children: formColorList(60));
複製代碼
這東西和css的flex有九分類似,還好我flex佈局玩的挺好:有興趣的可看這裏
Flow用起來麻煩不少,但可控制,靈活性更好,若是不是什麼逆天改命的佈局,Warp應該夠了
Wrap({
Key key,
this.direction = Axis.horizontal,
this.alignment = WrapAlignment.start,
this.spacing = 0.0,
this.runAlignment = WrapAlignment.start,
this.runSpacing = 0.0,
this.crossAxisAlignment = WrapCrossAlignment.start,
this.textDirection,
this.verticalDirection = VerticalDirection.down,
List<Widget> children = const <Widget>[],
})
複製代碼
var wrap_test = Wrap(
spacing: 8.0, // 列間距
runSpacing: 4.0, //行間距
direction:Axis.vertical ,
crossAxisAlignment:WrapCrossAlignment.center,
children: formColorList(50));
複製代碼
var wrap_test = Wrap(
spacing: 8.0, // 列間距
runSpacing: 4.0, //行間距
direction:Axis.horizontal ,
alignment:WrapAlignment.spaceBetween,
children: formColorList(50));
複製代碼
佈局勇士
,收穫三張傳說級卡片:- | - | - |
---|---|---|
NPC:好吧,我編不下去了...你們加油!
這裏先簡單看一下效果,明天根據例子來詳細分析具體用法
ListView,單獨能夠用,傳入一個Widget數組,批量生產ListView.builder簡潔些
ListView.builder({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
this.itemExtent,
@required IndexedWidgetBuilder itemBuilder,
int itemCount,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
int semanticChildCount,
複製代碼
豎直 | 水平 |
---|---|
//豎直
var list_view_test = ListView.builder(
itemCount: 20,
padding: EdgeInsets.all(8.0),
itemExtent: 60.0,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Center(child: Text('toly $index')),
);
},
);
//水平
var list_view_test = ListView.builder(
itemCount: 20,
padding: EdgeInsets.all(8.0),
scrollDirection:Axis.horizontal,
itemExtent: 60.0,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Center(child: Text('toly $index')),
);
},
);
複製代碼
GridView.count({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
@required int crossAxisCount,
double mainAxisSpacing = 0.0,
double crossAxisSpacing = 0.0,
double childAspectRatio = 1.0,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
List<Widget> children = const <Widget>[],
int semanticChildCount,
複製代碼
水平GridView | 豎直GridView |
---|---|
//豎直GridView
var grid_view_test = GridView.count(
crossAxisCount: 4,
children: List.generate(
100,
(index) {
return Card(
child: Center(child: Text('toly $index')),
);
},
),
);
//水平GridView
var grid_view_test = GridView.count(
crossAxisCount: 4,
scrollDirection:Axis.horizontal,
children: List.generate(
100,
(index) {
return Card(
child: Center(child: Text('toly $index')),
);
},
),
);
複製代碼
好吧,被它的名字騙了,和ListView並無太大的關係,也就是個多孩子的容器
優勢在於在指定軸上尺寸正常,另外一軸上會被拉伸,見圖:
A widget that arranges its children sequentially along a given axis,
forcing them to the dimension of the parent in the other axis.
一個widget,它按照給定的軸順序排列它的子部件,並迫使它們位於另外一個軸上的父軸的維度。
ListBody({
Key key,
this.mainAxis = Axis.vertical,
this.reverse = false,
List<Widget> children = const <Widget>[],
複製代碼
水平定 | 豎直定 |
---|---|
//豎直定
var list_body_test = Column(
children: <Widget>[
ListBody(
mainAxis: Axis.vertical,
reverse: false,
children: formColorList(5)
)],
);
//水平定
var list_body_test = Row(
children: <Widget>[
ListBody(
mainAxis: Axis.horizontal,
reverse: false,
children: formColorList(5)
)],
);
複製代碼
未精煉的傳說級卡片,更多屬性加成,戰士們,去精煉吧
- | - | - |
---|---|---|
將文字按照基線對齊(由於比較好看)--
baseline
越大,距離頂端越遠
const Baseline({
Key key,
@required this.baseline,
@required this.baselineType,
Widget child
複製代碼
formTextList(int count) {
var random = new Random();
var li = <Widget>[];
for (int i = 0; i < count; i++) {
li.add(new Baseline(
baselineType: TextBaseline.alphabetic,
child: new Text('Toly',
style: new TextStyle(
fontSize: 20.0 + random.nextInt(40),
textBaseline: TextBaseline.alphabetic,
),
),
baseline: 80,
));
}
return li;
}
var base_line_test = new Row(
children: formTextList(5),
);
複製代碼
這個挺有意思,兒子隨爺爺,父親(FractionallySizedBox)中間倒把手
能夠實現爺爺和孫子之間的尺寸比例聯繫
const FractionallySizedBox({
Key key,
this.alignment = Alignment.center,
this.widthFactor,
this.heightFactor,
Widget child,
複製代碼
var fsb_test = new Container(
color: Colors.blue,
height: 150.0,
width: 150.0,
child: new FractionallySizedBox(
alignment: Alignment.bottomCenter,
widthFactor: 1.5,
heightFactor: 0.5,
child: new Container(
color: Colors.red,
),
),
);
複製代碼
就是設定一個定比例的容器
width/height=aspectRatio
const AspectRatio({
Key key,
@required this.aspectRatio,
Widget child
複製代碼
var aspectratio_test = new Container(
width: 200.0,
child: new AspectRatio(
aspectRatio: 1.5,
child: new Container(
color: Colors.red,
),
),
);
複製代碼
佈局學徒
,獎勵卡片- | - | - |
---|---|---|
還剩幾個Box,明天寫幾個佈局例子順帶講一下,反正每一個新控件都會發張卡
最後把卡片總結起來,看看能不能湊夠兩幅撲克牌...打印出來當撲克牌打,還怕Flutter控件學不會?
好了,今天就到這裏,腦細胞死很多,趕快看幾集動漫補補腦。
//第一天:
3.如今焦點應該匯聚在StatefulWidget身上,不少地方都出現了,mark一下
---StatefulWidget是Widget的一個子類,是具備狀態的控件,可謂元老級別
4.canvas居然沒辦法畫文字,這不科學,mark一下
---保持mark
//第三天:
1.這裏mark一下Card裏的ShapeBorder shape,源碼粗略看了一下,可能挺好玩,今天主看控件
---保持mark
2.transform屬性的Matrix4有機會確定好好分析分析,mark一下
---保持mark
複製代碼
項目源碼 | 日期 | 備註 |
---|---|---|
V0.1-github | 2018-12-18 | Flutter第3天--基礎控件(上) |
筆名 | 微信 | 愛好 | |
---|---|---|---|
張風捷特烈 | 1981462002 | zdl1994328 | 語言 |
個人github | 個人簡書 | 個人掘金 | 我的網站 |
1----本文由張風捷特烈原創,轉載請註明
2----歡迎廣大編程愛好者共同交流
3----我的能力有限,若有不正之處歡迎你們批評指證,一定虛心改正
4----看到這裏,我在此感謝你的喜歡與支持