本文首發於公衆號「劉望舒」html
關聯繫列
ReactNative入門系列
React Native組件
Flutter基礎系列前端
學完了Dart語言,接下來就能夠學習Widget了,Flutter的UI界面就是由Widget組成的,Widget的數量繁多,所以我會用幾篇文章來專門介紹它,本篇就來介紹Basics Widget。java
Flutter的Widget的設計靈感來自於React,主要目的就是使用Widget構建UI。Widget根據其當前配置和狀態來描述視圖,當Widget的狀態發生更改時,Widget會重建其描述。framework將根據前面的描述進行對比,以肯定底層渲染樹從一個狀態轉換到下一個狀態所需的最小更改。 在Flutter中,除了Basics 的文本、圖片、卡片、輸入框這些基礎控件,佈局方式和動畫等也都是由Widget組成的。經過使用不一樣類型的Widget,就能夠實現複雜的界面。 Widget能夠翻譯爲部件,粗略的至關於Android中的View。Widget和View不一樣的是:Widget具備不一樣的生命週期:它是不可變的,每當Widget或者其狀態發生變化時,Flutter的框架都會建立一個新的Widget實例樹。相比之下,Android中的View會被繪製一次,而且在invalidate調用以前不會重繪。程序員
Widget的分類有不少類別,每一個類別下面又包含不少Widget,主要包括如下幾種類別:數組
Basics有些特殊,它是由Flutter官方從其餘的Widget分類中選取的一些Widget組成的,這些Widget是官方建議開發者構建第一個Flutter應用程序以前,須要知道的,目的是讓開發者更快的入門。好比Row屬於Layout分類,它就被選進了Basics中。本文遵循了Flutter官方的意圖,首先介紹Basics(Basics Widget)。bash
Widget更多的是以組合的形式存在,好比Container是屬於Layout中的一個Widget,而Container又由LimitedBox、 ConstrainedBox、Align、 Padding、 DecoratedBox、Transform部件組成。 若是要實現Container的自定義效果,能夠組合上面這些Widget以及其餘簡單的Widget,而不是將Container進行子類化實現。網絡
在Android中,咱們能夠經過直接更改View來更新視圖。可是在Flutter中,Widget是不可變的而且不會直接更新,而是必須使用Widget的狀態。 Widget有兩種狀態分類分別是無狀態的StatelessWidget和有狀態的StatefulWidget,StatelessWidget是不可變的,設置之後就不可再變化,全部的值都是最終的設置。StatefulWidget能夠保存本身的狀態,可是Widget是不可變的,所以須要配合State來保存狀態。 State擁有本身的聲明週期,以下所示:app
名稱 | 狀態 |
---|---|
initState | create以後被insert到渲染樹時調用的,只會調用一次 |
didChangeDependencies | state依賴的對象發生變化時調用 |
didUpdateWidget | Widget狀態改變時候調用,可能會調用屢次 |
build | 構建Widget時調用 |
deactivate | 當移除渲染樹的時調用 |
dispose | Widget即將銷燬時調用 |
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
...
),
),
);
}
}
複製代碼
上面的MaterialApp就是一個根Widget,也就是Flutter應用程序的第一個Widget,根Widget有如下幾種:框架
若是公司沒有特殊要求,這裏建議使用MaterialApp作爲根Widget就能夠了。less
Basics Widget也就是Basics,主要有如下幾種:
這裏選擇一些咱們必需要掌握的Basics Widget來進行講解。
爲了更好的理解這些Basics Widget,咱們須要寫一些例子,這些例子須要一個代碼模板,方便測試和學習。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(//1
title: 'Welcome to Flutter',
home: Scaffold(//2
appBar: AppBar(//3
title: Text('Basics Widget'),
),
body:
Padding(
padding: EdgeInsets.all(40.0),
child: Text('在這裏編寫和測試其餘Basics Widget'),
),
),
);
}
}
複製代碼
上面的代碼是稍微改動了官方的Hello World代碼,便於測試,具體的代碼含義已經在Flutter基礎(二)Flutter開發環境搭建和Hello World中講過了,這裏結合本文要講的內容再說點細節。註釋1處的MaterialApp屬於Material Components類別中的Widget,MaterialApp中包含了實現Material Design的應用程序所須要的Widget。 註釋2和3處的Scaffold和AppBar一樣也是Material Components類別中的Widget,Scaffold實現了Material Design佈局結構,AppBar是Material Design的應用欄,它們會在下一篇文章介紹Material Components時進行講解。效果以下圖所示:
在4.1小節中已經用了Text,還能夠定義樣式:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Basics Widget'),
),
body: Padding(
padding: EdgeInsets.all(60.0),
child: Text(
'文本樣式',
style: TextStyle(
fontSize: 16.0,
color: Colors.indigo,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.bold,
),
),
),
),
);
}
}
複製代碼
此次爲了便於理解列出了所有的代碼,此後的舉例只列出改變的部分。 經過TextStyle來定義文本的樣式,效果以下:
Image的構造函數有多種:
Image的屬性有不少種,主要的屬性爲fit,用於表示圖片的填充模式,參數類型爲BoxFit,BoxFit的取值主要有如下幾種,示例圖片來自flutter官方。
contain 全圖顯示,保持原比例。
child: Image.network(
"https://upload-images.jianshu.io/upload_images/1417629-53f7d0902457cbe6.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
width: 260,
height: 100,
fit: BoxFit.fill,
),
複製代碼
效果以下圖所示:
凸起按鈕RaisedButton是符合Material Design設計規範的按鈕,能夠經過onPressed來回調按鈕的點擊。
RaisedButton(
onPressed: () => print("onPressed"),
color: Colors.lightBlueAccent,
child: Text('RaisedButton', style: TextStyle(fontSize: 10)),
),
複製代碼
除了使用RaisedButton,flutter還提供了其餘的按鈕,好比FlatButton、IconButton、FloatingActionButton等等,它們的使用方法和RaisedButton大同小異,這裏就再也不贅述。
Basics Widget中的還有Row、Column、Container等Widget,這裏簡單介紹下。
Row Row用於在水平方向顯示數組中的子元素Widget。
child: Row(
children: <Widget>[
Icon(Icons.access_alarm),
Icon(Icons.add_a_photo),
Icon(Icons.add_call),
],
),
複製代碼
垂直方向顯示數組中的子元素Widget用Column,使用方法和Row同樣。這裏須要提到的是Expanded,能夠用Expanded來配合Row和Column使用,用來填充剩餘的空間。
Row(
children: <Widget>[
Icon(Icons.access_alarm),
Icon(Icons.add_a_photo),
Icon(Icons.add_call),
Expanded(
child: FittedBox(
fit: BoxFit.contain,
child: const FlutterLogo(), ), flex: 2, ), Expanded( child: Text( "佔剩餘部分的三分之一", ), flex: 1, ), ], ), 複製代碼
其中的Expanded的做用是在本身的尺寸範圍內縮放而且調整child位置,使得child適合其尺寸。FlutterLogo是Basics Widget中的一種,用於展現Flutter圖標。使用flex能夠調整兩個Expanded的佔比。
Container 一個便利的容器Widget,能夠設置Widget的背景、尺寸、定位。描述起來有些抽象,能夠理解它和Android中的ViewGroup差很少。
Container(
decoration:BoxDecoration(
color: Colors.lightGreen
),
child: Text('Container'),
padding: EdgeInsets.all(36.0),
margin: EdgeInsets.all(10.0),
),
複製代碼
Container的padding和margin屬性和Android中的做用是相似的:
本文主要介紹了什麼是Widget、Widget的分類、Basics Widget。由於Widget的數量繁多,官方將Widget進行了分類,並將須要先了解的Widget納入到了Basics Widget中,後續文章會介紹其餘的Widge分類。
分享大前端、Android、Java等技術,助力5萬程序員成長進階。