Flutter 即學即用系列博客——04 Flutter UI 初窺

前面三篇可以算是一個小小的里程碑。

主要是介紹了 Flutter 環境的搭建、如何創建 Flutter 項目以及如何在舊有 Android 項目引入 Flutter。

這一篇我們來學習下 Flutter 的 UI。

前言

說到 UI,我就簡單說下 Flutter 作為一門跨平臺語言具有的優勢之一,提高效率吧。

舉個例子:

假設現在要開發一個界面,Android 開發需要一天,iOS 開發也需要一天。那麼就是兩天。

如果你用 Flutter 開發,就只需要一天(因為 Android 和 iOS 都可以共用一套 Flutter 代碼)。這樣效率自然就提高了。

另外,假設後面產品發現界面有個位置需要調整,如果是 Android 或者 iOS 單獨開發,則兩個端都需要進行額外調整。

而 Flutter 就一套代碼而已,所以相較之下 Flutter 更易維護。

官網關於 UI 的介紹 User interface

這邊筆者按照自己的感受和認識進行說明。

讀者看完之後有了個基本的認識,後續不管是閱讀官方文檔還是使用搜索引擎搜索相關問題,相信會事半功倍。

記住一句話:

Flutter 裡面一切皆 Widget。

目錄

1. 基本配置

我們緊接之前文章,現在進入 MyApp/sub/my_flutter 位置。

打開 main.dart。如果提示下圖:

Dart support is not enabled for the project

我們點擊右邊第一個(Enabled Dart support)或者第二個(Open Dart settings)都是 OK 的。

如果點擊第二個,需要配置 dart 的目錄。

dart 的目錄在 flutter 的 bin 目錄下面的 cache 目錄下面。

舉個例子,筆者的 flutter bin 目錄(terminal 執行which flutter)為/Users/nesger/Desktop/nesger_folder/flutter/flutter/bin/,那麼 dart 目錄就在/Users/nesger/Desktop/nesger_folder/flutter/flutter/bin/cache/dart-sdk

然後直接拷貝下面代碼替換 main.dart 的代碼。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My Flutter'),
),
body: Center(),
)
);
}
}

實際編譯器可能會顯示如下圖,就是會有註釋顯示每個控件。

這有好處也有壞處。好處就是你可以看到哪一塊是哪一個 Widget。壞處就是視覺干擾。

這個是自動產生的,不可刪除。

可以通過如下操作控制是否顯示:

Android Studio->Preferences->Editor->General->Appearance

2. main.dart 學習

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My Flutter'),
),
body: Center(),
)
);
}
}


執行 flutter run 運行後可以看到下圖:

對比上面代碼可看到頂部藍色區域是 AppBar 這個 Widget 來控制的。

你可以自行修改 Text 裡面的內容然後按 r 鍵通過熱重載看下效果。

我們可以看到,Flutter 裡面的 dart 代碼一個比較明顯的地方就是一個 Widget 套著一個 Widget,有點樹形的樣子。

比如這裡

我們嘗試把 AppBar 去掉,可以看到界面顯示就是一片純白的界面。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(),
)
);
}


}

那麼這裡的 MaterialApp Widget 是不是必需的呢?

其實 MaterialApp 說明這個界面是按照 Material Design 的風格。

我們看下如果去掉會怎樣?

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(


body: Center(),
);
}
}

所以說 Scaffold 這個 Widget 不能直接返回,我們需要給它外面套一層 MaterialApp。

可以看下這個鏈接:https://github.com/nesger/FlutterNote/issues/4

我們返回之前的狀態,然後給他加一個 Hello World,看下怎樣?

我們知道,Flutter 一切皆 Widget,所以需要顯示 Hello World,就需要 Widget。

Widget 可以通過這個鏈接查看:https://flutter.io/docs/development/ui/widgets

可以看到 Text 這個 Widget

點擊進入

再點擊進入,可以看到介紹以及 Sample。

大家以後如果要看其他 Widget 也可以按照同樣的方式學習。

當然如果時間要求比較緊的話,大家學完博客可以直接在搜索引擎輸入關鍵字看下別人的 Sample,然後化用一下就沒問題啦。

我們點擊右邊複製,然後簡單修改如下:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Text(
'Hello World!',
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
),
),
),
);
}
}

可以看到我們將其放到 Center 這個 Widget 裡面,表示居中,同時作為它的一個 child。

大家可以試下去掉 Center 會怎樣,直接將 Text 作為 body,如下:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Text(
'Hello World!',
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
),
),
);
}
}

可以想象應該是不居中的。

到了這裡你應該可以發現,我們整個頁面其實是 body 對應的 Widget 來控制的。

上面我們的例子都是 MaterialApp,是不是一定只能這個 Widget 在最外層?

不是的,只是這裡 Scaffold 跟它配對而已,我們可以修改如下:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override


Widget build(BuildContext context) {
return Center(
child: Text(
'Hello, world!',
textDirection: TextDirection.ltr,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
),
);
}
}

注意多了一行textDirection: TextDirection.ltr,沒有會報錯。

3. 以 Text 為例子初窺 Widget 寫法

我們點進去 Text 源碼看下,

對比一下上面我們的代碼:

Text(
'Hello, world!',
textDirection: TextDirection.ltr,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
)

我們可以這樣認為,括號裡面的是待傳入參數。其中沒有花括號{}包裹的是必填項,有花括號{}的是選填項。

有花括號{}的在傳入參數時需要指定參數,格式為參數:值。不同參數之間逗號分隔。

所以我們可以猜測上面 Center 下面的 child 應該是在花括號裡面。所以才會有上面的寫法,我們跟進去源碼看看。

確實跟我們猜的一樣。而且由於參數的類型是 Widget,所以可以傳 Text 也是沒問題的。

所以到這裡你再回顧一下上面是不是就知道上面代碼的寫法了呢?

總結

由於 Flutter UI 內容比較多,講起來篇幅會比較大。

所以我們會拆分成幾篇文章進行講解。

回顧一下,本篇文章主要講解如下內容:

dart sdk 配置和 dart 源代碼括號後面編譯器提示的顯示和隱藏。通過 main.dart 的修改初步熟悉 Flutter 界面的寫法。通過 Text 說明如何在官方文檔上面查找控件和對應 Sample。通過一個具體的小控件 Text 初窺 Flutter Widget 的寫法和使用方法。

小彩蛋

這個彩蛋是微信群裡一個小夥伴說到的。這裡分享給大家。

簡單說就是設置 Android Studio 的背景圖。

先上圖

大家覺得哪種更加賞心悅目呢?

可以根據自己的喜好確定是否設置。

設置方法為

第一步:Android Studio->Preferences

第二步:點擊 Appearance,右邊的 Background image…

第三部:輸入圖片所在位置

其中 Opacity 是不透明度。

0 表示完全透明,跟沒設置一樣。100 表示完全不透明。

一般默認即可。

更多閱讀: