跳到主內容

面向 SwiftUI 開發者的 Flutter

學習如何將 SwiftUI 開發知識應用於構建 Flutter 應用。

想要使用 Flutter 編寫移動應用的 SwiftUI 開發者應該閱讀本指南。它解釋瞭如何將現有的 SwiftUI 知識應用到 Flutter 中。

Flutter 是一個使用 Dart 程式語言構建跨平臺應用的框架。要了解 Dart 程式設計與 Swift 程式設計之間的一些差異,請參閱 面向 Swift 開發者的 Dart 學習指南面向 Swift 開發者的 Flutter 併發程式設計

你在 SwiftUI 方面的知識和經驗在構建 Flutter 應用時非常有價值。

Flutter 在 iOS 和 macOS 上執行時也對應用行為進行了一些調整。要了解具體方式,請參閱 平臺適配

本文件可用作手冊,透過跳躍閱讀找到與你需求最相關的問題。本指南嵌入了示例程式碼。使用懸停或聚焦時出現的“在 DartPad 中開啟”按鈕,你可以在 DartPad 中開啟並執行部分示例。

概述

#

作為入門,請觀看以下影片。它概述了 Flutter 如何在 iOS 上工作以及如何使用 Flutter 構建 iOS 應用。

在新標籤頁中觀看 YouTube 影片:“面向 iOS 開發者的 Flutter”

Flutter 和 SwiftUI 程式碼描述了 UI 的外觀和工作方式。開發者將此類程式碼稱為宣告式框架

檢視 (Views) vs. 元件 (Widgets)

#

SwiftUI 將 UI 元件表示為檢視 (views)。你可以使用修飾符 (modifiers) 來配置檢視。

swift
Text("Hello, World!") // <-- This is a View
  .padding(10)        // <-- This is a modifier of that View

Flutter 將 UI 元件表示為元件 (widgets)

檢視和元件都只存在於需要改變之前。這些語言將此屬性稱為不可變性 (immutability)。SwiftUI 將 UI 元件屬性表示為檢視修飾符。相比之下,Flutter 對 UI 元件及其屬性都使用元件。

dart
Padding(                         // <-- This is a Widget
  padding: EdgeInsets.all(10.0), // <-- So is this
  child: Text("Hello, World!"),  // <-- This, too
)));

為了組合佈局,SwiftUI 和 Flutter 都會將 UI 元件相互巢狀。SwiftUI 巢狀檢視,而 Flutter 巢狀元件。

佈局流程

#

SwiftUI 使用以下流程佈局檢視:

  1. 父檢視向其子檢視提議一個尺寸。
  2. 所有後續子檢視
    • 它們的子檢視提議尺寸
    • 詢問該子檢視想要什麼尺寸
  3. 每個父檢視以返回的尺寸渲染其子檢視。

Flutter 的流程略有不同:

  1. 父元件將約束向下傳遞給其子元件。約束包括高度和寬度的最小值和最大值。

  2. 子元件嘗試決定其大小。它對其自身的子元件列表重複相同的過程:

    • 它通知其子元件關於子元件的約束。
    • 它詢問其子元件希望的大小。
  3. 父元件對子元件進行佈局。

    • 如果請求的尺寸符合約束,父元件則使用該尺寸。
    • 如果請求的尺寸不符合約束,父元件會將高度、寬度或兩者限制在約束範圍內。

Flutter 與 SwiftUI 的不同之處在於父元件可以覆蓋子元件所需的尺寸。元件不能擁有它想要的任何尺寸。它也無法知道或決定其在螢幕上的位置,因為該決定由其父元件做出。

要強制子元件以特定尺寸渲染,父元件必須設定緊密約束。當約束的最小值等於其最大值時,約束就變為了緊密約束。

SwiftUI 中,檢視可能會擴充套件到可用空間或將其尺寸限制為內容的大小。Flutter 元件的表現方式類似。

但是,在 Flutter 中,父元件可以提供無界約束。無界約束將其最大值設定為無窮大。

dart
UnboundedBox(
  child: Container(
      width: double.infinity, height: double.infinity, color: red),
)

如果子元件嘗試擴充套件且遇到無界約束,Flutter 會返回溢位警告。

dart
UnconstrainedBox(
  child: Container(color: red, width: 4000, height: 50),
)
When parents pass unbounded constraints to children, and the children are expanding, then there is an overflow warning.

要了解約束在 Flutter 中如何工作,請參閱 理解約束

設計系統

#

由於 Flutter 面向多個平臺,你的應用不需要遵循特定的設計系統。儘管本指南使用了 Material 元件,但你的 Flutter 應用可以使用許多不同的設計系統:

  • 自定義 Material 元件
  • 社群構建的元件
  • 你自己的自定義元件
  • Cupertino 元件(遵循 Apple 的《人機介面指南》)

在新標籤頁中觀看 YouTube 影片:“面向 iOS 開發者的 Flutter Cupertino 庫”

如果你正在尋找一個採用自定義設計系統的優秀參考應用,請檢視 Wonderous

UI 基礎

#

本節涵蓋了 Flutter UI 開發的基礎知識及其與 SwiftUI 的比較。這包括如何開始開發你的應用、顯示靜態文字、建立按鈕、響應按壓事件、顯示列表、網格等。

入門

#

SwiftUI 中,你使用 App 來啟動你的應用。

swift
@main
struct MyApp: App {
  var body: some Scene {
    WindowGroup {
      HomePage()
    }
  }
}

另一種常見的 SwiftUI 做法是將應用主體置於符合 View 協議的 struct 中,如下所示:

swift
struct HomePage: View {
  var body: some View {
    Text("Hello, World!")
  }
}

要啟動 Flutter 應用,請將應用的例項傳遞給 runApp 函式。

dart
void main() {
  runApp(const MyApp());
}

App 是一個元件。build 方法描述了它所代表的使用者介面部分。通常以 WidgetApp 類(例如 CupertinoApp)開始構建你的應用。

dart
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    // Returns a CupertinoApp that, by default,
    // has the look and feel of an iOS app.
    return const CupertinoApp(home: HomePage());
  }
}

HomePage 中使用的元件可能以 Scaffold 類開始。Scaffold 為應用實現了基本的佈局結構。

dart
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(body: Center(child: Text('Hello, World!')));
  }
}

注意 Flutter 是如何使用 Center 元件的。SwiftUI 預設在中心渲染檢視內容。Flutter 則並非總是如此。Scaffold 不會在螢幕中心渲染其 body 元件。要使文字居中,請將其包裹在 Center 元件中。要了解不同的元件及其預設行為,請檢視 元件目錄

新增按鈕

#

SwiftUI 中,你使用 Button 結構體來建立按鈕。

swift
Button("Do something") {
  // this closure gets called when your
  // button is tapped
}

要在 Flutter 中實現相同的結果,請使用 CupertinoButton 類:

dart
CupertinoButton(
  onPressed: () {
    // This closure is called when your button is tapped.
  },
  const Text('Do something'),
),

Flutter 為你提供了多種具有預定義樣式的按鈕。CupertinoButton 類來自 Cupertino 庫。Cupertino 庫中的元件使用 Apple 的設計系統。

水平對齊元件

#

SwiftUI 中,堆疊檢視在設計佈局時起著重要作用。兩個獨立的結構允許你建立堆疊:

  1. HStack 用於水平堆疊檢視

  2. VStack 用於垂直堆疊檢視

以下 SwiftUI 檢視將地球儀圖片和文字新增到水平堆疊檢視中:

swift
HStack {
  Image(systemName: "globe")
  Text("Hello, world!")
}

Flutter 使用 Row 而不是 HStack

dart
Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [Icon(CupertinoIcons.globe), Text('Hello, world!')],
),

Row 元件在 children 引數中需要一個 List<Widget>mainAxisAlignment 屬性告訴 Flutter 如何定位具有額外空間的子元件。MainAxisAlignment.center 將子元件定位在主軸的中心。對於 Row,主軸是水平軸。

垂直對齊元件

#

以下示例建立在上一節示例的基礎上。

SwiftUI 中,你使用 VStack 將元件排列成垂直柱狀。

swift
VStack {
  Image(systemName: "globe")
  Text("Hello, world!")
}

Flutter 使用與上一個示例相同的 Dart 程式碼,只是將 Row 替換為 Column

dart
Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [Icon(CupertinoIcons.globe), Text('Hello, world!')],
),

顯示列表檢視

#

SwiftUI 中,你使用 List 基礎元件來顯示序列項。要顯示模型物件序列,請確保使用者可以識別你的模型物件。要使物件可識別,請使用 Identifiable 協議。

swift
struct Person: Identifiable {
  var name: String
}

var persons = [
  Person(name: "Person 1"),
  Person(name: "Person 2"),
  Person(name: "Person 3"),
]

struct ListWithPersons: View {
  let persons: [Person]
  var body: some View {
    List {
      ForEach(persons) { person in
        Text(person.name)
      }
    }
  }
}

這類似於 Flutter 首選構建其列表元件的方式。Flutter 不需要列表項是可識別的。你設定要顯示的項數,然後為每一項構建一個元件。

dart
class Person {
  String name;
  Person(this.name);
}

final List<Person> items = [
  Person('Person 1'),
  Person('Person 2'),
  Person('Person 3'),
];

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: items.length,
        itemBuilder: (context, index) {
          return ListTile(title: Text(items[index].name));
        },
      ),
    );
  }
}

Flutter 對列表有一些注意事項:

  • ListView 元件有一個 builder 方法。這類似於 SwiftUI 的 List 結構體中的 ForEach

  • ListViewitemCount 引數設定 ListView 顯示多少項。

  • itemBuilder 有一個 index 引數,其範圍在 0 到 itemCount 減 1 之間。

前面的示例為每一項返回一個 ListTile 元件。ListTile 元件包含 heightfont-size 等屬性。這些屬性有助於構建列表。但是,Flutter 允許你返回幾乎任何代表你的資料的元件。

顯示網格

#

SwiftUI 中構建非條件網格時,你使用帶有 GridRowGrid

swift
Grid {
  GridRow {
    Text("Row 1")
    Image(systemName: "square.and.arrow.down")
    Image(systemName: "square.and.arrow.up")
  }
  GridRow {
    Text("Row 2")
    Image(systemName: "square.and.arrow.down")
    Image(systemName: "square.and.arrow.up")
  }
}

要在 Flutter 中顯示網格,請使用 GridView 元件。此元件有各種建構函式。每個建構函式的目標相似,但使用不同的輸入引數。以下示例使用 .builder() 初始化器:

dart
const widgets = <Widget>[
  Text('Row 1'),
  Icon(CupertinoIcons.arrow_down_square),
  Icon(CupertinoIcons.arrow_up_square),
  Text('Row 2'),
  Icon(CupertinoIcons.arrow_down_square),
  Icon(CupertinoIcons.arrow_up_square),
];

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GridView.builder(
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
          mainAxisExtent: 40,
        ),
        itemCount: widgets.length,
        itemBuilder: (context, index) => widgets[index],
      ),
    );
  }
}

SliverGridDelegateWithFixedCrossAxisCount 委託確定網格用於佈局其元件的各種引數。這包括決定每行顯示專案數的 crossAxisCount

SwiftUI 的 Grid 和 Flutter 的 GridView 的不同之處在於 Grid 需要 GridRowGridView 使用委託來決定網格應該如何佈局其元件。

建立滾動檢視

#

SwiftUI 中,你使用 ScrollView 來建立自定義滾動元件。以下示例以可滾動的方式顯示一系列 PersonView 例項。

swift
ScrollView {
  VStack(alignment: .leading) {
    ForEach(persons) { person in
      PersonView(person: person)
    }
  }
}

為了建立滾動檢視,Flutter 使用 SingleChildScrollView。在以下示例中,函式 mockPerson 模擬了 Person 類的例項,以建立自定義的 PersonView 元件。

dart
SingleChildScrollView(
  child: Column(
    children: mockPersons
        .map((person) => PersonView(person: person))
        .toList(),
  ),
),

響應式與自適應設計

#

SwiftUI 中,你使用 GeometryReader 來建立相對檢視尺寸。

例如,你可以:

  • geometry.size.width 乘以某個因子來設定寬度
  • 使用 GeometryReader 作為斷點來改變應用的設計。

你還可以使用 horizontalSizeClass 檢視尺寸類是 .regular 還是 .compact

要在 Flutter 中建立相對檢視,你可以使用以下兩個選項之一:

  • LayoutBuilder 類中獲取 BoxConstraints 物件。
  • 在構建函式中使用 MediaQuery.of() 來獲取當前應用的大小和方向。

要了解更多資訊,請檢視 建立響應式和自適應應用

狀態管理

#

SwiftUI 中,你使用 @State 屬性包裝器來表示 SwiftUI 檢視的內部狀態。

swift
struct ContentView: View {
  @State private var counter = 0;
  var body: some View {
    VStack{
      Button("+") { counter+=1 }
      Text(String(counter))
    }
  }}

SwiftUI 還包括用於更復雜狀態管理的其他選項,例如 ObservableObject 協議。

Flutter 使用 StatefulWidget 管理本地狀態。使用以下兩個類實現有狀態元件:

  • StatefulWidget 的子類
  • State 的子類

State 物件儲存元件的狀態。要改變元件的狀態,請從 State 子類中呼叫 setState(),以告訴框架重新繪製元件。

以下示例展示了計數器應用的一部分:

dart
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('$_counter'),
            TextButton(
              onPressed: () => setState(() {
                _counter++;
              }),
              child: const Text('+'),
            ),
          ],
        ),
      ),
    );
  }
}

要了解更多管理狀態的方法,請檢視 狀態管理

動畫

#

存在兩種主要型別的 UI 動畫。

  • 隱式動畫,從當前值動畫到新的目標值。
  • 顯式動畫,在被要求時進行動畫處理。

隱式動畫

#

SwiftUI 和 Flutter 採用相似的動畫方法。在這兩個框架中,你都需要指定 duration(持續時間)和 curve(曲線)等引數。

SwiftUI 中,你使用 animate() 修飾符來處理隱式動畫。

swift
Button("Tap me!"){
   angle += 45
}
.rotationEffect(.degrees(angle))
.animation(.easeIn(duration: 1))

Flutter 包含用於隱式動畫的元件。這簡化了常用元件的動畫處理。Flutter 以以下格式命名這些元件:AnimatedFoo

例如:要旋轉按鈕,請使用 AnimatedRotation 類。這會對 Transform.rotate 元件進行動畫處理。

dart
AnimatedRotation(
  duration: const Duration(seconds: 1),
  turns: turns,
  curve: Curves.easeIn,
  TextButton(
    onPressed: () {
      setState(() {
        turns += .125;
      });
    },
    const Text('Tap me!'),
  ),
),

Flutter 允許你建立自定義隱式動畫。要組合一個新的動畫元件,請使用 TweenAnimationBuilder

顯式動畫

#

對於顯式動畫,SwiftUI 使用 withAnimation() 函式。

Flutter 包含格式如 FooTransition 的顯式動畫元件。一個示例是 RotationTransition 類。

Flutter 還允許你使用 AnimatedWidgetAnimatedBuilder 建立自定義顯式動畫。

要了解更多關於 Flutter 動畫的資訊,請參閱 動畫概述

在螢幕上繪圖

#

SwiftUI 中,你使用 CoreGraphics 在螢幕上繪製線條和形狀。

Flutter 擁有一個基於 Canvas 類的 API,其中包含兩個幫助你繪圖的類:

  1. CustomPaint(需要一個 painter)

    dart
    CustomPaint(
      painter: SignaturePainter(_points),
      size: Size.infinite,
    ),
    
  2. CustomPainter(實現你在畫布上繪圖的演算法)

    dart
    class SignaturePainter extends CustomPainter {
      SignaturePainter(this.points);
    
      final List<Offset?> points;
    
      @override
      void paint(Canvas canvas, Size size) {
        final Paint paint = Paint()
          ..color = Colors.black
          ..strokeCap = StrokeCap.round
          ..strokeWidth = 5;
        for (int i = 0; i < points.length - 1; i++) {
          if (points[i] != null && points[i + 1] != null) {
            canvas.drawLine(points[i]!, points[i + 1]!, paint);
          }
        }
      }
    
      @override
      bool shouldRepaint(SignaturePainter oldDelegate) =>
          oldDelegate.points != points;
    }
    
#

本節解釋如何在應用頁面之間導航、推送 (push) 和彈出 (pop) 機制等。

#

開發者使用不同的頁面構建 iOS 和 macOS 應用,這些頁面稱為導航路由 (navigation routes)

SwiftUI 中,NavigationStack 表示此頁面堆疊。

以下示例建立一個顯示人物列表的應用。要在一個新的導航連結中顯示人物詳情,請點選該人物。

swift
NavigationStack(path: $path) {
  List {
    ForEach(persons) { person in
      NavigationLink(
        person.name,
        value: person
      )
    }
  }
  .navigationDestination(for: Person.self) { person in
    PersonView(person: person)
  }
}

如果你有一個沒有複雜連結的小型 Flutter 應用,請使用帶有命名路由的 Navigator。定義導航路由後,透過名稱呼叫你的導航路由。

  1. 在傳遞給 runApp() 函式的類中為每個路由命名。以下示例使用 App

    dart
    // Defines the route name as a constant
    // so that it's reusable.
    const detailsPageRouteName = '/details';
    
    class App extends StatelessWidget {
      const App({super.key});
    
      @override
      Widget build(BuildContext context) {
        return CupertinoApp(
          home: const HomePage(),
          // The [routes] property defines the available named routes
          // and the widgets to build when navigating to those routes.
          routes: {detailsPageRouteName: (context) => const DetailsPage()},
        );
      }
    }
    

    以下示例使用 mockPersons() 生成人物列表。點選一個人會使用 pushNamed() 將該人的詳情頁面推送到 Navigator

    dart
    ListView.builder(
      itemCount: mockPersons.length,
      itemBuilder: (context, index) {
        final person = mockPersons.elementAt(index);
        final age = '${person.age} years old';
        return ListTile(
          title: Text(person.name),
          subtitle: Text(age),
          trailing: const Icon(Icons.arrow_forward_ios),
          onTap: () {
            // When a [ListTile] that represents a person is
            // tapped, push the detailsPageRouteName route
            // to the Navigator and pass the person's instance
            // to the route.
            Navigator.of(
              context,
            ).pushNamed(detailsPageRouteName, arguments: person);
          },
        );
      },
    ),
    
  2. 定義顯示每個人物詳情的 DetailsPage 元件。在 Flutter 中,你可以在導航到新路由時將引數傳遞到元件中。使用 ModalRoute.of() 提取引數:

    dart
    class DetailsPage extends StatelessWidget {
      const DetailsPage({super.key});
    
      @override
      Widget build(BuildContext context) {
        // Read the person instance from the arguments.
        final Person person = ModalRoute.of(context)?.settings.arguments as Person;
        // Extract the age.
        final age = '${person.age} years old';
        return Scaffold(
          // Display name and age.
          body: Column(children: [Text(person.name), Text(age)]),
        );
      }
    }
    

要建立更高階的導航和路由需求,請使用路由包,例如 go_router

要了解更多資訊,請檢視 導航和路由

手動返回

#

SwiftUI 中,你使用 dismiss 環境值來彈出並返回上一個螢幕。

swift
Button("Pop back") {
  dismiss()
}

Flutter 中,使用 Navigator 類的 pop() 函式:

dart
TextButton(
  onPressed: () {
    // This code allows the
    // view to pop back to its presenter.
    Navigator.of(context).pop();
  },
  child: const Text('Pop back'),
),
#

SwiftUI 中,你使用 openURL 環境變數來開啟指向另一個應用的 URL。

swift
@Environment(\.openURL) private var openUrl

// View code goes here

Button("Open website") {
  openUrl(
    URL(
      string: "https://google.com"
    )!
  )
}

Flutter 中,使用 url_launcher 外掛。

dart
CupertinoButton(
  onPressed: () async {
    await launchUrl(Uri.parse('https://google.com'));
  },
  const Text('Open website'),
),

主題、樣式和媒體

#

你可以輕鬆設定 Flutter 應用的樣式。樣式設定包括在淺色和深色主題之間切換、更改文字和 UI 元件的設計等。本節涵蓋如何為你的應用設定樣式。

使用深色模式

#

SwiftUI 中,你在 View 上呼叫 preferredColorScheme() 函式以使用深色模式。

Flutter 中,你可以在應用級別控制淺色和深色模式。要控制亮度模式,請使用 App 類的 theme 屬性:

dart
const CupertinoApp(
  theme: CupertinoThemeData(brightness: Brightness.dark),
  home: HomePage(),
);

文字樣式

#

SwiftUI 中,你使用修飾符函式來設定文字樣式。例如,要更改 Text 字串的字型,請使用 font() 修飾符:

swift
Text("Hello, world!")
  .font(.system(size: 30, weight: .heavy))
  .foregroundColor(.yellow)

要在 Flutter 中設定文字樣式,請將 TextStyle 元件新增為 Text 元件的 style 引數的值。

dart
Text(
  'Hello, world!',
  style: TextStyle(
    fontSize: 30,
    fontWeight: FontWeight.bold,
    color: CupertinoColors.systemYellow,
  ),
),

設定按鈕樣式

#

SwiftUI 中,你使用修飾符函式來設定按鈕樣式。

swift
Button("Do something") {
  // Do something when the button is tapped.
}
.font(.system(size: 30, weight: .bold))
.background(Color.yellow)
.foregroundColor(Color.blue)

要在 Flutter 中設定按鈕元件的樣式,請設定其子元件的樣式,或直接修改按鈕本身的屬性。

在以下示例中:

  • CupertinoButtoncolor 屬性設定其顏色。
  • 子元件 Textcolor 屬性設定按鈕文字的顏色。
dart
child: CupertinoButton(
  color: CupertinoColors.systemYellow,
  onPressed: () {},
  child: const Text(
    'Do something',
    style: TextStyle(
      color: CupertinoColors.systemBlue,
      fontSize: 30,
      fontWeight: FontWeight.bold,
    ),
  ),
),

使用自定義字型

#

SwiftUI 中,你可以分兩步在應用中使用自定義字型。首先,將字型檔案新增到你的 SwiftUI 專案中。新增檔案後,使用 .font() 修飾符將其應用到你的 UI 元件。

swift
Text("Hello")
  .font(
    Font.custom(
      "BungeeSpice-Regular",
      size: 40
    )
  )

Flutter 中,你透過名為 pubspec.yaml 的檔案來管理資源。此檔案與平臺無關。要將自定義字型新增到你的專案,請按照以下步驟操作:

  1. 在專案的根目錄下建立一個名為 fonts 的資料夾。這是一個可選步驟,有助於組織你的字型。

  2. 將你的 .ttf.otf.ttc 字型檔案新增到 fonts 資料夾中。

  3. 開啟專案中的 pubspec.yaml 檔案。

  4. 找到 flutter 部分。

  5. fonts 部分下新增你的自定義字型。

    yaml
    flutter:
      fonts:
        - family: BungeeSpice
          fonts:
            - asset: fonts/BungeeSpice-Regular.ttf
    

將字型新增到專案後,你可以像以下示例那樣使用它:

dart
Text(
  'Cupertino',
  style: TextStyle(fontSize: 40, fontFamily: 'BungeeSpice'),
),

在應用中捆綁圖片

#

SwiftUI 中,你首先將圖片檔案新增到 Assets.xcassets,然後使用 Image 檢視來顯示圖片。

要在 Flutter 中新增圖片,請遵循與新增自定義字型類似的方法:

  1. 將一個 images 資料夾新增到根目錄。

  2. 將此資源新增到 pubspec.yaml 檔案中。

    yaml
    flutter:
      assets:
        - images/Blueberries.jpg
    

新增圖片後,使用 Image 元件的 .asset() 建構函式來顯示它。此建構函式:

  1. 使用提供的路徑例項化給定的圖片。
  2. 從捆綁在應用中的資源中讀取圖片。
  3. 在螢幕上顯示圖片。

要檢視完整示例,請檢視 Image 文件。

在應用中捆綁影片

#

SwiftUI 中,你分兩步將本地影片檔案與你的應用捆綁在一起。首先,你匯入 AVKit 框架,然後例項化一個 VideoPlayer 檢視。

Flutter 中,將 video_player 外掛新增到你的專案中。此外掛允許你從同一個程式碼庫建立一個可在 Android、iOS 和 Web 上執行的影片播放器。

  1. 將外掛新增到你的應用中,並將影片檔案新增到你的專案中。
  2. 將資源新增到你的 pubspec.yaml 檔案中。
  3. 使用 VideoPlayerController 類來載入和播放你的影片檔案。

要檢視完整的操作步驟,請檢視 video_player 示例