Views
在flutter中,什麼相當於一個View呢?
在安卓中,View時顯示在屏幕上最基礎的部分,包括Buttons,toolbars, and inputs, 這些都是一個View的子控件。而在flutter中,Widget相當於View。Widgets雖然跟Android裏的Views不完全一樣,本質上是一樣的。
但是,這些與View有一些區別。首先,小部件具有不同的生命週期:它們是不可變的,只有在需要更改時才存在。每當窗口小部件或其狀態發生變化時,Flutter的框架都會創建一個新的窗口小部件實例樹。相比之下,Android視圖被繪製一次,並且在調用invalidate之前不會重繪
Flutter的小部件很輕巧,部分原因在於它們的不變性。因爲它們本身不是視圖,並且不是直接繪製任何東西,而是對UI及其語義的描述,這些描述被“誇大”到引擎蓋下的實際視圖對象中。
這些是實現Material Design準則的小部件。 Material Design是一個靈活的設計系統,適用於所有平臺,包括iOS。
怎樣刷新Widgets的顯示?
在Android中,您可以通過直接更改視圖來更新視圖。但是,在Flutter中,窗口小部件是不可變的,不會直接更新,而是必須使用窗口小部件的狀態。
這就是有狀態和無狀態小部件的概念來源。 StatelessWidget聽起來就像是一個沒有狀態信息的小部件。
當您描述的用戶界面部分不依賴於對象中的配置信息時,StatelessWidgets非常有用。
例如,在Android中,這類似於將帶有徽標的ImageView放置。徽標在運行時不會改變,因此請在Flutter中使用StatelessWidget。
如果要根據在進行HTTP調用或用戶交互後收到的數據動態更改UI,則必須使用StatefulWidget並告訴Flutter框架該窗口小部件的狀態已更新,以便它可以更新該窗口小部件。
這裏需要注意的重要一點是,無狀態和有狀態小部件的行爲都是相同的。它們重建每一幀,區別在於StatefulWidget有一個State對象,它跨幀存儲狀態數據並恢復它。
如果您有疑問,那麼請始終記住此規則:如果窗口小部件發生更改(例如,由於用戶交互),則它是有狀態的。但是,如果窗口小部件對更改做出反應,則包含父窗口小部件仍然可以是無狀態的,如果它本身不會對更改做出反應。
以下示例顯示如何使用StatelessWidget。常見的StatelessWidget是Text小部件。如果你看一下Text小部件的實現,你會發現它是StatelessWidget的子類。
Text(
'I like Flutter!',
style: TextStyle(fontWeight: FontWeight.bold),
);
正如您所看到的,Text Widget沒有與之關聯的狀態信息,它呈現了在其構造函數中傳遞的內容,僅此而已。
但是,如果你想讓“I Like Flutter”動態變化,例如點擊FloatingActionButton會怎樣?
要實現此目的,請將Text小部件包裝在StatefulWidget中,並在用戶單擊按鈕時更新它。
import 'package:flutter/material.dart';
void main() {
runApp(SampleApp());
}
class SampleApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
// Default placeholder text
String textToShow = "I Like Flutter";
void _updateText() {
setState(() {
// update the text
textToShow = "Flutter is Awesome!";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: Center(child: Text(textToShow)),
floatingActionButton: FloatingActionButton(
onPressed: _updateText,
tooltip: 'Update Text',
child: Icon(Icons.update),
),
);
}
}
我們應該怎樣放置 widgets? Where is my XML layout file?
在之前Android開發,你一般是以XML的形式來定義佈局,但是在flutter裏是以widget tree的形式
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: Center(
child: MaterialButton(
onPressed: () {},
child: Text('Hello'),
padding: EdgeInsets.only(left: 10.0, right: 10.0),
),
),
);
}
如何自定義小部件Widget
在Android中,我們一般使用的控件都是View的子類,或使用預先存在的視圖來覆蓋和實現實現所需行爲的方法。
在Flutter中,通過組合較小的小部件(而不是擴展它們)來構建自定義小部件。 它有點類似於在Android中實現自定義ViewGroup,其中所有構建塊都已存在,但您提供了不同的行爲 - 例如,自定義佈局邏輯。
例如,如何構建一個在構造函數中採用標籤的CustomButton? 創建一個CustomButton,它使用標籤組成RaisedButton,而不是通過擴展RaisedButton
class CustomButton extends StatelessWidget {
final String label;
CustomButton(this.label);
@override
Widget build(BuildContext context) {
return RaisedButton(onPressed: () {}, child: Text(label));
}
}
在FLutter中有類似Intents的東東嗎?
在Android中,Intents有兩個主要用例:在Activities之間導航,以及與組件通信。另一方面,Flutter沒有意圖的概念,儘管你仍然可以通過本機集成(使用插件)啓動意圖。
在FLutter裏面沒有直接的Activity和Fragment;相反,在Flutter中,您可以使用導航器和路徑在屏幕之間導航,所有這些都在同一個Activity中。
路徑是應用程序的“屏幕”或“頁面”的抽象,導航器是管理路徑的窗口小部件。路線粗略地映射到活動,但它沒有相同的含義。導航器可以推送和彈出路徑以在屏幕之間移動。導航器的工作方式類似於堆棧,您可以在其上推送()要導航到的新路由,並且當您想要“返回”時可以從中彈出()路由。
在Android中,您在應用程序的AndroidManifest.xml中聲明您的活動。
在Flutter中,您有幾個選項可以在頁面之間導航:
指定路徑名稱的映射。 (MaterialApp)
直接導航到路線。 (WidgetApp)
以下示例構建一個Map
void main() {
runApp(MaterialApp(
home: MyAppHome(), // becomes the route named '/'
routes: <String, WidgetBuilder> {
'/a': (BuildContext context) => MyPage(title: 'page A'),
'/b': (BuildContext context) => MyPage(title: 'page B'),
'/c': (BuildContext context) => MyPage(title: 'page C'),
},
));
}