Upgrade to Pro — share decks privately, control downloads, hide ads and more …

好想要 Swift iOS App 也能有的 Flutter & Jetpack Compos...

好想要 Swift iOS App 也能有的 Flutter & Jetpack Compose 功能

Transcript

  1. • 因為教課跟新鮮感,開始學習開發 Flutter & Jetpack Compose App • 發現新世界,認識 一

    些好想要 Swift iOS App 也能有的 Flutter & Jetpack Compose 功能 • 參加 PK 的選 手 • Apple vs Google • Swift vs Dart vs Kotlin • SwiftUI / UIKit vs Flutter vs Jetpack Compose • Xcode vs VS Code vs Android Studio • Apple、iOS、Swift、Xcode、SwiftUI、UIKit 還是最棒的 為什麼會好想要 ?
  2. • IDE • 程式語 言 • SDK • 官 方

    開發 文 件 & 學習資源 大 綱
  3. • Swift • 開發 Swift iOS App 必須要有 Mac Xcode

    或 iPad Swift Playground • 沒有官 方 線上寫 Swift 和開發 iOS App 的網站 • 沒有 Mac 也能練習 Swift 的程式網站 • 只能寫 Swift 程式,不能寫 App • 租借雲端 Mac 開發 iOS App • 遠端桌 面 連線 • Mac Stadium、 MacinCloud、Amazon EC2 Mac 希望 Apple 也有線上開發 iOS App 的 工 具 線上開發 工 具
  4. • Flutter & Dart • DartPad • 開發簡單的 Flutter App

    或 Dart 程式 • 利 用 gist 分享 Flutter 程式 • 結合 Gemini AI 修改程式 線上開發 工 具
  5. • Flutter • Firebase Studio • 開發完整的 Flutter App •

    預覽執 行 Android & Web App (不能預覽 iOS) • 類似 VS Code 的操作介 面 和功能 • 結合 Gemini AI 修改程式 線上開發 工 具 畫圖請 AI 製作畫 面
  6. • Kotlin • Kotlin Playground • 方 便地分享程式,讓別 人 瀏覽、修改和執

    行 程式 • 可執 行 Compose Multiplatform App 
 (ps: API 跟 Jetpack Compose 有 一 些差異) 線上開發 工 具
  7. • Jetpack Compose • Firebase Studio 的 Android Studio Cloud

    • 跑在雲端的 Android Studio 希望 Apple 也能有雲端開發 App 的 Xcode 線上開發 工 具
  8. • 測試 iPhone 實機 一 定要 手 上有 iPhone 實機

    • 測試 Android 實機可使 用 Firebase 提供的 Android Device Streaming • 從 Android Studio 啟動雲端的 Android 手 機 希望 Xcode 之後也能提供雲端的 iPhone 測試 雲端實機測試
  9. • Xcode 沒有內建 Terminal • VS Code 內建 Terminal •

    搭配 GitHub Copilot 的 AI 功能 • 比 方 在 Terminal 問 AI 問題,請 AI 執 行 指令 • 自 動完成提 示 • Android Studio 內建 Terminal AI 常常會在 Terminal 執 行 任務 IDE 內建 Terminal
  10. Xcode 無法調整 調整 IDE 介 面 的 文 字 icon

    大 小 ,比 方 側邊欄 Navigator 可稍微調整
  11. VS Code & Android Studio 可調整 調整 IDE 介 面

    的 文 字 icon 大 小 ,比 方 側邊欄 • VS Code • cmd + 放 大 ,cmd - 縮 小 • Window: Zoom Level • Android Studio • Zoom Android Studio VS Code
  12. • iOS 模擬器無法拍照 • Android 模擬器可以拍照 • 預設的圖片 • 使

    用 電腦的鏡頭拍照,將 Front / Rear 設成 Webcam0 Android 模擬器有拍照功能(Camera) Android 模擬器的拍照畫 面 Android 模擬器的前後鏡 頭設定
  13. VS Code & Android Studio 有豐富的外掛 VS Code & Android

    Studio 有滿滿的外 掛, 而 且有許多 AI 功能的外掛 Xcode 只有少少的外掛 VS Code 共同編輯程式的外掛 Live Share VS Code 的 Material Icon Theme
  14. • Xcode • 滑鼠游標移到程式上,按住 option 鍵再點擊滑鼠左鍵 • VS Code &

    Android Studio • 滑鼠游標移到程式上即可顯 示 說明(Documentation on Hover) 希望 Xcode 也能滑鼠游標移到程式上顯 示 說明 顯 示 程式說明 VS Code 的 Flutter Text 說明
  15. • Android Studio 自 動在 Kotlin 參數前加上參數名提 示 的 Inlay

    Hints 沒寫參數名時,IDE 會 自 動加上參數名提 示 calculateBMI(height = 175.0, weight = 70.0) calculateBMI(175.0, 70.0)
  16. 執 行 App 才能看到 SwiftUI & UIKit 的 view hierarchy

    Xcode 的 view hierarchy • Debug View Hierarchy • Debug View Hierarchy 時 App 不能操作 • 只有讀取功能,不能直接修改更新畫 面
  17. • VS Code 的 Flutter outline 可在沒執 行 App 時看到

    widget tree • 點選 widget tree 裡的 widget 會標 示 出對 應的程式 • 點選程式也會標 示 出 widget tree 裡對應 的 widget • 程式範例 • VS Code 的 Flutter inspector & Android Studio 的 Layout Inspector 可查看執 行 中 App 的畫 面 並進 行 部分修改, 而 且 App 仍 然可以操作 Flutter 的 widget tree & Flutter inspector (VS Code)
  18. SwiftUI 有多層元件時,Xcode 不容易 一 眼看出 } 對應的元件 struct ContentView: View

    { var body: some View { ZStack { Color.yellow .ignoresSafeArea() VStack { Text("最棒的程式語 言 ") HStack { Image(systemName: "swift") Text("Swift") } } } } } 游標在 } 時,對應的 { 會閃 一 下
  19. VS Code & Android Studio 的 closing labels 提 示

    Flutter 的 ) 可以 一 眼看出對應的元件 長得像 // 開頭的注解,但是不能編 輯 Android Studio VS Code
  20. VS Code 的 Bracket pair colorization •連結 •標注不同顏 色 的括號,

    方 便區分 •Android Studio 可另外安裝套件 Rainbow Brackets
  21. • Xcode 的 embed 要 自己 輸入元件的名字 • embed 只能包住

    一 個選取的元件,無法包住多個 • 沒有移除元件的 unembed • 以上問題可以 用 Xcode 的 AI 解決 SwiftUI 加入 / 移除 UI 元件 Xcode 的 Coding tools
  22. • VS Code & Android Studio 的 wrap widget /

    remove widget / move widget • wrap 可包住多個選取的元件。 Flutter 加入 / 移除 UI 元件 VS Code Android Studio
  23. • Android Studio 的 Surround with widget / Remove wrapper

    • Surround 可包住多個選取的元件。 Jetpack Compose 加入 / 移除 UI 元件
  24. • 輸入程式時可看到 asset 的顏 色 • 程式不會顯 示 顏 色

    • 程式顯 示 顏 色 的特例 • 打起來有點 麻 煩的 #colorLiteral() Xcode 顯 示 顏 色
  25. • 程式顯 示 顏 色 • Flutter • Jetpack Compose

    (ps: 內建定義好的顏 色 不會顯 示 ,比 方 Color.Red) • 輸入程式時可看到 Flutter 內建的顏 色 顯 示 顏 色 Android Studio for Flutter & Jetpack Compose
  26. • 自 動完成 • Gutter 會顯 示 圖案 Flutter Icon

    (VS Code & Android Studio) 顯 示 symbol / icon VS Code & Android Studio VS Code & Android Studio
  27. • SwiftUI & UIKit 修改程式時不會更新模擬器和實機執 行 中的 App • 可透過第三

    方工 具 InjectionIII 實現 • SwiftUI & UIKit 修改程式時可更新 preview 執 行 中的 App • preview 可能只是某個畫 面 ,不是整個 App • 修改程式時狀態會回到初始狀態,不會保留原本的狀態 • 範例 • 修改數字的顏 色 時變回數字 1 SwiftUI & UIKit 修改程式時更新執 行 中的 App
  28. • 修改程式時更新模擬器和實機執 行 中的 App • 修改程式時會保留原本的狀態 • 範例 •

    修改數字的顏 色 時會維持原來的數字 • Flutter 3.35 新增 preview 元件的功能 • 從 Chrome 看 preview,修改程式時會保留原本的狀態 Flutter 的 Hot Reload (VS Code & Android Studio) 修改程式時立即更新執 行 中的 App
  29. • 修改程式時更新模擬器和實機執 行 中的 App • 修改程式時會保留原本的狀態 • 範例 •

    修改數字的顏 色 時會維持原來的數字 Jetpack Compose 的 Live Edit (Android Studio) 修改程式時立即更新執 行 中的 App
  30. • 目 前沒有 自 動 import • 曾經有 自 動

    import,但是做得不太好,後來被移除了 • 沒有 import 時輸入不認識的程式不會有 自 動完成 • 可以 用 Xcode AI 的 Generate Fix 幫忙 import Xcode 從選單輸入程式後 自 動 import
  31. Flutter 的 自 動 import • VS Code & Android

    Studio 都可 自 動 import • 沒有 import 時輸入不認識的程式也有 自 動完成 • 從選單點選程式會 自 動 import,比 方 點選上圖的 Random() 會 import 'dart:math' • Quick Fix 也可幫忙 import • 範例
  32. Jetpack Compose 的 自 動 import • 範例 • Android

    Studio 可 自 動 import • 沒有 import 時輸入不認識的程式也有 自 動完成 • 從選單點選程式會 自 動 import,比 方 點選上圖的 Random 會 import kotlin.random.Random • 從修正的選單可點選 import
  33. • Xcode 只能設定 一 段式快速鍵,常常會覺得不夠 用 ,常 用 的快速鍵 都被設定了

    • VS Code 的兩段式快速鍵範例: 展開程式區塊 連續按下兩個快速鍵組合 VS Code 的兩段式快速鍵(Key Chord)
  34. • Xcode • GPT-5(Thinking)、GPT-5、GPT-4.1 • 若有訂閱 Claude 可使 用 Claude。

    • 加入 API key 可使 用 其它 AI,但是要花錢。(ps: 可免費加入本機 AI) 希望 Xcode 能免費提供更多 AI model,比 方 Claude & Gemini 不花錢可使 用 的 AI model 面
  35. • VS Code • GitHub Copilot 免費提供 Claude Sonnet 3.5、GPT-5

    mini、 GPT-4.1、o3-mini • 訂閱 ChatGPT 的朋友可使 用 Codex • Android Studio & Firebase Studio • lightweight version of Gemini 2.5 Pro • Gemini 2.5 in Firebase Studio 不花錢可使 用 的 AI model
  36. • Rename • Rethink variable names • 比 方 找出

    function 定義裡的變數,
 像是參數和 local variable Android Studio rename 時 AI 提供建議
  37. • Xcode 的 AI 目 前還無法連網查資料 • VS Code 的

    GitHub Copilot 使 用 AI 連網查 文 件資料
  38. Xcode 使 用 AI 執 行 程式以外的操作 • 比 方

    加套件(package)、設定 App 存取相機的 權限、加圖到專案 • Xcode Coding Assistant 目 前只會改程式 • 加套件 • Xcode Coding Assistant 只會指引我們 手 動加套件,不會幫我們加 • 請 AI 實作需要套件的功能時必須 自己手 動 加套件,AI 無法獨立完成功能
  39. • Xcode 的 GUI 可以 方 便地加套件(package)、設定 App 權限、加 圖,但是

    AI 反 而 很難執 行 指令或修改檔案實現這些功能 • 請其它 AI 使 用 SPM 幫 Xcode 專案加套件常常會出問題,因為會修 改 project.pbxproj,有時成功,有時失敗,甚 至 造成專案打不開 • 範例: 使 用 GitHub Copilot for Xcode 使 用 AI 執 行 程式以外的操作
  40. VS Code AI 自 動加入套件 webview_ fl utter • AI

    可以 方 便地執 行 指令或修改檔案幫 Flutter App 加套件(package)、 設定 App 權限、加圖 • AI 實作功能時可依需要 自 動加套件 • 範例: 加入網 頁 顯 示 https://www.youtube.com/watch? v=_E821In6oKo   • 範例: 請 AI 設定 Android App 的權限,比 方 相機權限。相反的,請 AI 幫 Xcode 的 iOS App 加權限還不太 行 使 用 AI 執 行 程式以外的操作
  41. • Xcode 的 AI 尚未 支 援 MCP Server •

    GitHub Copilot for Xcode 支 援 MCP Server • VS Code 支 援 MCP Server • Android Studio 支 援 MCP Server • Dart and Flutter MCP server • AI 可以更聰明地開發 Flutter App,幫忙我 們解決各種 Flutter 問題 • 應 用 : 修正 runtime error、搜尋安裝適合的 套件 • GitHub MCP Server、Firebase MCP server 希望 Xcode 支 援 MCP Server,Swift 有官 方 的 MCP Server MCP Server Fix runtime 的排版錯誤
  42. • Xcode • 要設定 token,有點 麻 煩 • VS Code

    & Android Studio • 透過 OAuth,不 用 設定 token,打開網 頁 登入 GitHub 即可。 • VS Code • Android Studio 上傳程式到 GitHub VS Code Android Studio 希望 Xcode 不 用 設定 token
  43. •VS Code •執 行 commit 時會 自 動 生 成

    commit message •也可在 prompt 請 AI 進 行 commit 和 git 的相關操作 (ps: Xcode AI 目 前只會改程式,不能執 行 指令) • GitHub MCP Server、GitHub CLI •Android Studio AI 自 動 生 成 commit message
  44. Swift 必須依照順序傳入參數 不照順序傳入參數 func add(number1: Int = 1, number2: Int

    = 2) -> Int { return number1 + number2 } func main() { var sum = add(number1: 10, number2: 20) }
  45. Dart & Kotlin 可不照順序傳入參數,不 用 記順序, 方 便隨時補上參數 不照順序傳入參數 int

    add({int number1 = 1, int number2 = 2}) { return number1 + number2; } void main() { var sum = add(number1: 10, number2: 20); sum = add(number2: 200, number1: 100); } Dart named parameters fun add(number1: Int = 1, number2: Int = 2): Int { return number1 + number2 } fun main() { var sum = add(number1 = 10, number2 = 20); sum = add(number2 = 200, number1 = 100) } Kotlin
  46. • Swift • 危險的做法: force unwrap ! • 較安全的做法需搭配 optional

    binding • if let 或 guard let 讀取可能無值的變數內容 var girlFriend: String? = "Wendy" if let girlFriend { print("可愛的 💞" + girlFriendName) } else { print("沒有 girlfriend 😭") }
  47. 可能無值的變數在確認有值時可直接使 用 void main() { int? number = 2; int

    doubleNumber = number * 2; } void calculate(int? number) { if (number != null) { int doubleNumber = number * 2; print(doubleNumber); } } Dart 的 type promotion 不需要另外轉型
  48. 可能無值的變數在確認有值時可直接使 用 Kotlin 的 Smart Cast fun calculate(number: Int?) {

    if (number != null) { val doubleNumber = number * 2 println(doubleNumber) } }
  49. 其它 Dart type promotion 例 子 if (book is Book)

    { return Scaffold( appBar: AppBar( title: Text(book.name), ), • Dart 用 is 判斷後不 用 再轉型 • Swift 用 is 判斷後還是要轉型,通常會 用 optional binding 搭配 as?
  50. ??= Dart 的 null-aware assignment operator int? a; // =

    null a ??= 3; print(a); // <-- Prints 3. a ??= 5; print(a); // <-- Still prints 3. 無值時才存入,有值時不會,防 止 覆蓋已有的數值
  51. Swift 設定 property 的建構 子 (initializer、constructor) class Baby { var

    name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } } 寫起來有點 麻 煩,雖然 Xcode 可以幫忙 一 鍵 生 成
  52. Dart 的 Initializing formal parameter 方 便設定 property 的建構 子

    class Baby { String name; int age; Baby(this.name, this.age); } void main() { Baby baby = Baby('peter', 18); } class Baby(var name: String, var age: Int) fun main() { var baby = Baby("peter", 1) } Kotlin
  53. Dart 用 _ 開頭當 private class _MyHomePageState extends State<MyHomePage> {

    int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } • 型別名、變數名、function 名以 _ 開頭即為 private • 對應 Swift 的 fi leprivate,同檔案內可存取 • 範例: 預設 project 的 Counter App
  54. 問題: Swift 對物件進 行 多次操作時要打很多次物件名字 void main() { var cuteBaby

    = Baby(name: 'Peter', age: 1, weight: 10.0, height: 75.0); cuteBaby.name = 'John'; cuteBaby.age = 2; cuteBaby.weight = 12.0; cuteBaby.height = 80.0; cuteBaby.sleep(); }
  55. • 官 方文 件 解法: Dart 兩個點的 Cascade notation ..

    void main() { var cuteBaby = Baby(name: 'Peter', age: 1, weight: 10.0, height: 75.0) ..name = 'John' ..age = 2 ..weight = 12.0 ..height = 80.0 ..sleep(); } ps: Kotlin 可 用 apply function
  56. Swift 必須 用 fl apMap 或 + 實現,有點 麻 煩

    將集合裡的多個成員展開,加到另 一 個集合 let listOne = [1, 2, 3] let listTwo = [4, 5, 6] let combinedList1 = [[0], listOne, listTwo].flatMap { $0 } print(combinedList1) let combinedList2 = [0] + listOne + listTwo print(combinedList2) [0, 1, 2, 3, 4, 5, 6] [0, 1, 2, 3, 4, 5, 6]
  57. 將集合裡的多個成員展開,加到另 一 個集合 Spread operator void main() { List<int> listOne

    = [1, 2, 3]; List<int> listTwo = [4, 5, 6]; var combinedList1 = [0, listOne, listTwo]; print(combinedList1); var combinedList2 = [0, ...listOne, ...listTwo]; print(combinedList2); } [0, [1, 2, 3], [4, 5, 6]] [0, 1, 2, 3, 4, 5, 6] 三個點的 Dart …
  58. 將集合裡的多個成員展開,加到另 一 個集合裡 Spread operator fun main() { val arrayOne

    = arrayOf(1, 2, 3) val arrayTwo = arrayOf(4, 5, 6) val combinedArray1 = arrayOf(0, arrayOne, arrayTwo) println(combinedArray1.contentDeepToString()) val combinedArray2 = arrayOf(0, *arrayOne, *arrayTwo) println(combinedArray2.contentToString()) } [0, [1, 2, 3], [4, 5, 6]] [0, 1, 2, 3, 4, 5, 6] Kotlin 的 *
  59. • Swift 不能在集合裡使 用 if 和 for • Swift 的

    ResultBuilder 讓 SwiftUI 可使 用 if & ForEach 調整畫 面 • Dart 的 collection if 和 collection for • Flutter 可彈性排版畫 面 在集合裡使 用 if 和 for void main() { var numbersList = [ for (var i = 1; i <= 10; i++) if (i % 2 == 0) i ]; print(numbersList); } [2, 4, 6, 8, 10]
  60. • mixin 是特殊的類別,其它類 別可使 用 with 得到 mixin 的 property

    & method,不 用 繼 承。 • 使 用 with 可得到多個 mixin 功能,克服單 一 繼承的限制。 • document 同時得到多個類別功能的 Dart mixin mixin Swimming { String name; void swim() { print('I can swim'); } } mixin Flying { void fly() { print('I can fly'); } } class Duck with Swimming, Flying { void display() { print('I am a duck'); } }
  61. • SwiftUI 沒有開源,只有 Swift 開源 • 可以看到 Flutter & Jetpack

    Compose 背後的程式怎麼寫的 • Flutter • Jetpack Compose Open Source 的 Flutter & Jetpack Compose 範例: Flutter 圓 角 卡片 Container 實作的程式
  62. • UIKit & SwiftUI 的內建 UI 元件不多,很多東 西 要 自己

    實作 • Flutter 的 UI 元件(widget)超多 • widget index • Widget catalog • 例 子 : CircleAvatar(圓形圖片) UI 元件數量 CircleAvatar( radius: 100, backgroundImage: NetworkImage( 'https://developer.apple.com/assets/elements/icons/memoji/ resources-g_2x.png', ), )
  63. 將資料回傳到上 一 頁 • SwiftUI & UIKit 有很多資料回傳的 方 法,比

    方 binding、environment、 delegate、noti fi cation、closure,要花 一 點時間學習 • Flutter 有個直覺的 方 法 • 範例 final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => const AddTodoPage()), ); Navigator.pop(context, Todo(name: _controller.text, time: _selectedDate)); 顯 示 下 一頁 並等待回傳的資料 (放 心 ,不會卡住 App) 回上 一頁 時傳入回傳的資料
  64. • SwiftUI & UIKit 只有使 用 者要 自己 關掉的 alert,必須

    自己 實作 自 動消失 的 文 字,比 方 使 用 Task、asyncAfter、Timer • Flutter 範例 • Jetpack Compose 範例 在螢幕下 方 出現幾秒後 自 動消失的 文 字 Flutter & Jetpack Compose 的 snack bar ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Button Pressed')), );
  65. • SwiftUI & UIKit 必須 自 己 實作,通常會使 用 第

    三 方 套件 • Flutter 官 方 範例 • Jetpack Compose 範例 Flutter & Jetpack Compose 的 drawer(側邊欄)
  66. • UIKit 的 UIColor & SwiftUI 的 Color 沒有內建傳入 十

    六進位的 RGB 和 Alpha,只能傳入 十 進位 • Flutter & Jetpack Compose 的顏 色 可傳入 十 六進位的 ARGB 十 六進位的顏 色 Color(red: 28/255, green: 100/255, blue: 50/255) Alpha、Red、Green、Blue
  67. • UIKit 的 UIImage • 有點 麻 煩,利 用 CGAnimateImageDataWithBlock

    & CGAnimateImageAtURLWithBlock 產 生 CGImage • SwiftUI 的 WebView 或 Image 搭配 UIImage • WebView(url: URL(string: "https:// www.animatedimages.org/data/media/209/animated- cat-image-0072.gif")) • Flutter 的 Image • Image.asset('assets/animated-cat-image-0072.gif') • Image.network('https://www.animatedimages.org/ data/media/209/animated-cat-image-0072.gif') 顯 示 GIF
  68. Flutter & Jetpack Compose 的 Column / Row 可設定三種等間距 spaceEvenly

    spaceBetween spaceAround 頭尾的間距是元件間間距的 一 半 • UIKit UIStackView 只有 spaceBetween 的效果 • SwiftUI VStack & HStack 要搭配 Spacer 自己 實現這三種間距
  69. Flutter Column / Row 用 MainAxisAlignment 設定等間距 class MyHomePage extends

    StatelessWidget { const MyHomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Text('🦊', style: TextStyle(fontSize: 50)), Text('🐨', style: TextStyle(fontSize: 50)), Text('🐰', style: TextStyle(fontSize: 50)), ], ), ), ); } }
  70. Jetpack Compose Column / Row 用 Arrangement 設定等間距 @Composable fun

    MyHomePage(modifier: Modifier = Modifier) { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Row( horizontalArrangement = Arrangement.SpaceAround, modifier = Modifier.fillMaxWidth() ) { Text( text = "🦊", fontSize = 50.sp ) Text( text = "🐨", fontSize = 50.sp ) Text(
  71. 設定比例 • 範例: 紅 色 和藍 色 的寬度是 2:3 •

    UIKit & SwiftUI 需要比較複雜的 方 法實現 • UIKit • auto layout 的 multiplier • SwiftUI • GeometryReader、 containerRelativeFrame、 自 訂 Layout
  72. Flutter 設定比例的 Expanded fl ex class MyHomePage extends StatelessWidget {

    const MyHomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Row( children: [ Expanded(flex: 2, child: Container(color: Colors.red)), Expanded(flex: 3, child: Container(color: Colors.blue)), ], ), ); } }
  73. Jetpack Compose 設定比例的 Modi fi er weight @Composable fun ProportionalLayout(modifier:

    Modifier = Modifier) { Row { Box( modifier = Modifier .weight(2f) .fillMaxHeight() .background(Color.Red) ) Box( modifier = Modifier .weight(3f) .fillMaxHeight() .background(Color.Blue) ) } }
  74. 由左 而 右排列,空間不夠時排到下 一 排 • UIKit & SwiftUI 需要比較複雜的

    方 法實現 • UIKit • 定義 UICollectionViewFlowLayout • SwiftUI • 定義 Layout
  75. Flutter 的 Wrap widget @override Widget build(BuildContext context) { return

    Scaffold( body: SafeArea( child: Wrap( direction: Axis.horizontal, spacing: 20, runSpacing: 10, children: books .map((book) => Container(color: Colors.amber, child: Text(book))) .toList(), ), ), ); } • Wrap 官 方文 件 • Jetpack Compose 也有類似的元 件: FlowRow & FlowColumn
  76. • SwiftUI & UIKit 必須 自己 實現圓 角 陰影 效果

    • Card 文 件 • Flutter Card 程式範例 • GPT 5: 請 用 Flutter Card widget 製 作漂亮的冰島介紹 頁面 ,包含六張網 路上的漂亮冰島照片 圓 角 卡片陰影樣式 Flutter & Jetpack Compose 的 Card
  77. • Swift 要 自己 取名 • Flutter • VoidCallback (沒有參數沒有回傳)

    • ValueChanged (有 一 個參數沒有回傳) 將常 見 的 function 型別取名 typedef VoidCallback = void Function(); typedef ValueChanged<T> = void Function(T value);
  78. • SwiftUI & UIKit 必須 自己 實現 • Flutter &

    Jetpack Compose 都有 Carousel • Flutter 官 方 的 CarouselView 範例 水 平滑動, 目 前正在瀏覽的項 目 放 大 ,兩旁的項 目 縮 小 ,製造遠近感 Carousel(輪轉介 面 )
  79. • SwiftUI & UIKit 必須 自 己 實作 • Flutter

    的 Slider 可透過參數 label 在上 方 顯 示 數值 • Flutter 官 方 Slider 範例 • Flutter & Jetpack Compose 選擇區間的 RangeSlider • Flutter官 方 RangeSlider 範例 Slider 的上 方 顯 示 數值 & 選擇區間的 RangeSlider
  80. • SwiftUI & UIKit 必須 自己 實作 • Segmented buttons

    • Menus • Radio Button • Checkbox • Chips • Switch
 Flutter & Jetpack Compose 有很多選東 西 的元件
  81. • 範例: 表單的 email 格式有問題時顯 示 紅 色 錯誤訊息 •

    SwiftUI & UIKit 必須 自己 實作 • SwiftUI 也有 Form,可惜只有顯 示 功 能,沒有資料驗證 驗證使 用 者輸入的資料
  82. • 驗證資料, 方 便管理表單的狀態和資料送出 的 行 為 • 輸入的資料有問題時顯 示

    紅 色 錯誤訊息 • 官 方 範例: 利 用 validator 驗證回傳錯誤訊息 Flutter 驗證資料的 Form & TextFormField 程式連結
  83. 上 方 切換分 頁 的 tab bar & 水 平捲動切換分

    頁 • Tab 設計 文 件 • 上 方 切換分 頁 的 tab bar • SwiftUI & UIKit 必須 自己 實作 • Flutter • DefaultTabController、 TabBar、TabBarView • 內建 水 平捲動切換分 頁 • tab 很多時可 水 平捲動 tab  • Jetpack Compose • PrimaryTabRow & SecondaryTabRow • 可實現兩層分 頁 兩層分 頁
  84. 浮動按鈕 ( fl oating Action Button) floatingActionButton: FloatingActionButton( onPressed: _incrementCounter,

    tooltip: 'Increment', child: const Icon(Icons.add), ) •SwiftUI & UIKit 必須 自己 實作 •Flutter & Jetpack Compose 內建 •Flutter Counter 範例 •Jetpack Compose 範例
  85. Flutter 的 ThemeData: 設定顏 色 、字體、元件樣式、dark theme  統 一 設計

    App 樣式的 Theme Jetpack Compose 的 MaterialTheme: 設定顏 色 、字體、形狀、dark theme SwiftUI & UIKit 有 一 些設定 App 樣式的 方 法,不過沒有類似 theme 這樣 方 便將 顏 色 & 字體設定在 一 個地 方 的 方 法
  86. • Flutter for SwiftUI Developers • Flutter for UIKit developers

    • Learning Dart as a Swift developer Flutter & Dart 提供其它平台開發者變 心 學習的教學 希望 Apple 也有 SwiftUI(UIKit) for Flutter Developers、Learning Swift as a Dart developer
  87. • Apple 大 部份是 WWDC 分享新技術的影片,比較少適合新 手 的教 學影片 •

    Flutter Widget of the Week(YouTube) • 一 兩分鐘快速上 手 元件的功能和程式寫法 • 範例 希望 Apple 也能拍 SwiftUI(UIKit) view of the Week 官 方 的 Flutter UI 元件教學短影片
  88. • Apple 網 頁 上的範例要 自己 選取複製 • cmd +

    a 會複製整個網 頁 ,無法只複製程式區塊 ! • 範例 • Introducing SwiftUI • The Swift Programming Language 一 鍵複製範例程式
  89. • Flutter、Dart、Jetpack Compose、Kotlin 官網的範例都有提供複 製鍵或 cmd + a 複製 •

    範例 • Building user interfaces with Flutter • Introduction to Dart • What is Jetpack Compose? 希望 Apple 網 頁 的範例也有複製鍵或 cmd + a 複製 一 鍵複製範例程式
  90. • 範例 • Flutter: Create a horizontal list • Flutter:

    Form class • Dart cheatsheet ps: SwiftUI & UIKit 不像 Flutter 可 生 成網 頁 ,要在網 頁 上看到 App 畫 面 有困難 希望 Apple 教學 文 件也能直接修改執 行 範例 & 使 用 AI Flutter & Dart 教學 文 件可直接修改執 行 範例 & 使 用 AI
  91. • 範例: Authenticate with Firebase using Password-Based Accounts on Apple

    Platforms 希望 Apple 教學 文 件也能提供 AI 說明程式 Firebase 文 件提供 AI 一 鍵說明程式
  92. • Apple 的 API 文 件有中 文 版,但是教學 文 件只有英

    文 版 • 範例: Android 基本概念:使 用 Compose 希望 Apple 教學 文 件也有中 文 版 官 方 中 文 版的教學