Flutter Cupertino 教程:如何構建外觀和感覺原生的 iOS 應用

杭州程式設計師張張發表於2022-07-14

所有前端應用程式都使用某種設計系統來幫助使用者更輕鬆地完成任務。他們可能會使用內部開發的定製設計系統或成熟的設計系統,例如 Material Design 或 Cupertino (iOS)。

Material Design 由 Google 開發,可用於開發 Android、iOS、Web 和桌面應用程式。

Cupertino 由 Apple 開發。它基於 Apple 的人機介面指南,該指南實現了當前的 iOS 設計語言。

Flutter SDK 附帶 MaterialCupertino 小部件庫,用於開發一個外觀和感覺都適用於任一平臺的應用程式。

你仍然可以僅僅使用Material widgets庫來構建一個應用程式。然而,如果你想建立一個看起來像標準iOS風格的應用程式,你應該強烈考慮使用Cupertino庫。

在本教程中,我們將構建一個底部有三個選項卡的簡單應用程式;通話聊天設定

通話標籤上,我們將新增簡單的導航欄;聊天標籤將顯示會員列表,並允許終端使用者搜尋任何會員;在設定標籤上,我們將使用各種Cupertino風格的部件來建立設定頁面。

這是最終應用程式的外觀:

1.建立一個簡單的頁面

讓我們先建立一個簡單的頁面,在頂部顯示頁面標題,在中間顯示 "Hello "資訊。要建立這樣一個頁面,你必須刪除新建立的專案的所有內容,用下面的程式碼代替它:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'simple_page.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]).then((value) => runApp(MyApp()));
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    // 1 <-- SEE HERE
    return CupertinoApp(
      // 2 <-- SEE HERE
      theme: CupertinoThemeData(brightness: Brightness.light),
      home: CupertinoSimpleHomePage(),
    );
  }
}

class CupertinoSimpleHomePage extends StatefulWidget {
  const CupertinoSimpleHomePage({Key? key}) : super(key: key);

  @override
  _CupertinoSimpleHomePageState createState() =>
      _CupertinoSimpleHomePageState();
}

class _CupertinoSimpleHomePageState extends State<CupertinoSimpleHomePage> {
  @override
  Widget build(BuildContext context) {
    // 3 <-- SEE HERE
    return const CupertinoPageScaffold(
      // 4 <-- SEE HERE
      navigationBar: CupertinoNavigationBar(
        middle: Text('Chat App'),
      ),
      child: Center(
        child: Text('Hi'),
      ),
    );
  }
}

程式碼說明:

  • CupertinoApp:CupertinoApp小元件允許你新增小元件,這些小元件主要用於建立一個iOS風格的應用程式。
  • CupertinoThemeData:使用此小部件,您可以指定應用的樣式
  • CupertinoPageScaffoldCupertinoPageScaffold 有助於構建頁面的佈局,例如新增導航欄
  • CupertinoNavigationBar:這個小部件建立一個看起來像原生 iOS 風格的導航欄。

輸出

2.新增tabs

這些選項卡用於支援應用程式的主要導航。讓我們在底部新增三個選項卡,每個選項卡都有不同的名稱和圖示。要建立標籤,我們必須將 CupertinoPageScaffold 替換為 CupertinoTabScaffold

// 1 <-- SEE HERE
return CupertinoTabScaffold(
  // 2 <-- SEE HERE
  tabBar: CupertinoTabBar(
    currentIndex: 1,
    items: const <BottomNavigationBarItem>[
      // 3 <-- SEE HERE
      BottomNavigationBarItem(
          icon: Icon(CupertinoIcons.phone), label: 'Calls'),
      BottomNavigationBarItem(
          icon: Icon(CupertinoIcons.chat_bubble_2), label: 'Chats'),
      BottomNavigationBarItem(
          icon: Icon(CupertinoIcons.settings), label: 'Settings'),
    ],
  ),
  tabBuilder: (context, index) {
    late final CupertinoTabView returnValue;
    switch (index) {
      case 0:
        // 4 <-- SEE HERE
        returnValue = CupertinoTabView(builder: (context) {
          return const CupertinoPageScaffold(
              navigationBar: CupertinoNavigationBar(
                middle: Text('Calls'),
              ),
              child: Center(child: Text('Calls')));
        });
        break;
      case 1:
        returnValue = CupertinoTabView(
          builder: (context) {
            return CupertinoChatPage();
          },
        );
        break;
      case 2:
        returnValue = CupertinoTabView(
          builder: (context) {
            return CupertinoSettingsPage();
          },
        );
        break;
    }
    return returnValue;
  },
);
  • CupertinoTabScaffold: CupertinoTabScaffold小元件包含引數,如 tabBartabBuilder,允許你建立tab bar專案和tab bar檢視。
  • CupertinoTabBarCupertinoTabBar 小部件在螢幕底部新增標籤欄。它使用名為 BottomNavigationBarItem 的小部件顯示多個專案。 currentIndex 屬性允許您控制應用程式啟動時的活動選項卡
  • BottomNavigationBarItem: 這個小元件在標籤欄上顯示了一個item。它包含有用的引數,如圖示、標籤和背景顏色來建立一個item。
  • CupertinoTabViewCupertinoTabView 小部件負責為選定選項卡填充內容。每個 CupertinoTabView 都有自己的導航堆疊。

輸出

3.新增滾動時隱藏的 NavigationBar

在前面的步驟中,我們已經構建了一個基本設定,我們可以在此基礎上開始新增更多小部件。

在當前示例中,當向下滾動列表時,基本導航欄始終位於頂部。我們可以透過在使用者開始滾動時隱藏導航欄來改善使用者體驗。

步驟

  • 第 1 步:在 CupertinoTabView 內部,返回 CustomScrollView
  • 第 2 步:在 CustomScrollView 中,新增 CupertinoSliverNavigationBar 小部件。此小部件在滾動時隱藏導航欄。
  • 第 3 步:在 CupertinoSliverNavigationBar 內部,新增 largeTitle 引數以顯示導航標題。

程式碼

CupertinoTabView(
  builder: (context) {
    return CustomScrollView(
      slivers: <Widget>[
        CupertinoSliverNavigationBar(
          largeTitle: Text('Chats'),
        ),
      ],
    );
  },
);

輸出

4.顯示載入指示器

要顯示載入指示器,您可以使用 CupertinoActivityIndi​​cator 小部件。這個小部件顯示了一個按順時針方向旋轉的 iOS 風格的活動指示器。讓我們使用帶有 Text 小部件的 CupertinoActivityIndi​​cator 來顯示“等待網路”指示。

步驟

  • 第 1 步:在 CupertinoSliverNavigationBar 內部,新增中間引數並分配 Row 小部件。
  • 第 2 步:在 Row 小部件中,新增 CupertinoActivityIndi​​cator
  • 第 3 步:再新增一個小部件(即 Text 小部件)

程式碼:

CupertinoSliverNavigationBar(
  largeTitle: Text('Chats'),
  leading: Text(
    'Edit',
    style: TextStyle(color: CupertinoColors.link),
  ),
  middle: Row(
    mainAxisSize: MainAxisSize.min,
    children: const [
      CupertinoActivityIndicator(),
      SizedBox(width: 8),
      Text('Waiting for network')
    ],
  ),
)

輸出

5.啟動搜尋

讓我們用一些使用者填充“聊天”選項卡並實現搜尋功能。

為此,我們將:

  • 建立 users 模型類
  • 用它來填充一些使用者資料
  • 使用自定義 list tile小部件顯示
  • 使用 CupertinoSearchTextField 小部件啟用搜尋

步驟:

步驟 1:建立使用者列表。

const List<User> users = const <User>[
  const User('Jack', Colors.greenAccent),
  const User('Lucy', Colors.green),
  const User('Luna', Colors.black26),
  const User('Oliver', Colors.blue),
  const User('Lily', Colors.amberAccent),
  const User('Milo', Colors.purple),
  const User('Max', Colors.pink),
  const User('Kitty', Colors.yellowAccent),
  const User('Simba', Colors.red),
  const User('Zoe', Colors.blueAccent),
  const User('Jasper', Colors.deepOrange),
  const User('Stella', Colors.cyan),
  const User('Lola', Colors.lightBlue),
  const User('Halsey', Colors.deepPurpleAccent),
  const User('Taylor', Colors.indigoAccent),
];

第2步:將所有使用者複製到 filteredUsers 中。

List<User> _filteredUsers = users;

第 3 步:新增 SliverGrid 小部件並使用filteredUsers在任何可滾動檢視中顯示使用者列表。

SliverGrid(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 1,
    childAspectRatio: 5,
  ),
  delegate: SliverChildBuilderDelegate(
    (BuildContext context, int index) {
      return UserTile(_filteredUsers[index]);
    },
    childCount: _filteredUsers.length,
  ),
)

第 4 步:在 CupertinoSliverNavigationBar 下方,新增帶有 FractionallySizedBoxClipRectSliverToBoxAdapter 小部件。

第 5 步:將 CupertinoSearchTextField 小部件新增為子小部件。 CupertinoSearchTextField 小部件類似於普通的 Textfield 小部件,但還模仿了 iOS 樣式的外觀和行為。

SliverToBoxAdapter(
  child: FractionallySizedBox(
    widthFactor: 0.9,
    child: ClipRect(
        child: Padding(
      padding: const EdgeInsets.only(top: 16),
      child: CupertinoSearchTextField(
        controller: _controller,
        onChanged: (value) {
          _updateUserList(value);
        },
        onSubmitted: (value) {
          _updateUserList(value);
        },
        onSuffixTap: () {
          _updateUserList('');
        },
      ),
    )),
  ),
)

第 6 步:新增 _updateUsersList() 方法以查詢與搜尋詞匹配的使用者。

void _updateUserList(String value) {
  debugPrint('$value');

  if (value.length > 0) {
    _filteredUsers = _filteredUsers
        .where((element) =>
            element.name.toLowerCase().contains(value.toLowerCase()))
        .toList();
  } else {
    _controller.text = '';
    _filteredUsers = users;
  }

  setState(() {});
}

輸出

6.新增開關switch

使用 CupertinoSwitch 小部件,您可以在應用程式中建立 iOS 樣式開關。讓我們在“設定”選項卡中新增 CupertinoSwitch 小部件。

程式碼

CupertinoFormSection(
  header: Text('Account Details'),
  children: [
    CupertinoFormRow(
      prefix: Text('Chat Backup'),
      child: CupertinoSwitch(
        value: chatBackup,
        onChanged: (value) {
          setState(() {
            chatBackup = !chatBackup;
          });
        },
      ),
    ),
  ],
),

輸出

7.顯示ActionSheet

要顯示 ActionSheet,您可以使用 CupertinoActionSheet 小部件。此小部件用於允許使用者在多個條目之間進行選擇。

步驟:

  • 第 1 步:新增 CupertinoButton 小部件。
  • 第 2 步:在 onPressed 方法中,呼叫 showCupertinoModalPopup
  • 第 3 步:在 showCupertinoModalPopup 的構建器中,返回 CupertinoActionSheet
  • 第 4 步:在 CupertinoActionSheet 中,使用 CupertinoActionSheetAction 小部件返回一些操作。

程式碼

Center(
  child: CupertinoButton(
    onPressed: () {
      showCupertinoModalPopup<void>(
        context: context,
        builder: (BuildContext context) => CupertinoActionSheet(
          title: const Text('Set Wallpaper Theme'),
          actions: <CupertinoActionSheetAction>[
            CupertinoActionSheetAction(
              child: const Text('Dark'),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
            CupertinoActionSheetAction(
              child: const Text('Light'),
              onPressed: () {
                Navigator.pop(context);
              },
            )
          ],
        ),
      );
    },
    child: const Text('Chat Wallpaper'),
  ),
)

輸出

8.顯示AlertDialog

要顯示 AlertDialog,您可以使用 CupertinoAlertDialog 小部件。 CupertinoAlertDialog 小部件用於確認使用者的操作——例如,在刪除帳戶時。

步驟:

  • 第 1 步:新增 CupertinoButton 小部件。
  • 第 2 步:在 onPressed 方法中,呼叫 showCupertinoDialog
  • 第 3 步:在 showCupertinoDialog 的構建器中返回 CupertinoAlertDialog
  • 第 4 步:在 CupertinoAlertDialog 中,使用 CupertinoDialogAction 小部件返回一些操作。

程式碼:

Center(
  child: CupertinoButton(
    onPressed: () {
      showCupertinoDialog<void>(
        context: context,
        builder: (BuildContext context) => CupertinoAlertDialog(
          title: const Text('Delete chat'),
          content: const Text('Proceed with deleting chat?'),
          actions: <CupertinoDialogAction>[
            CupertinoDialogAction(
              child: const Text('No'),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
            CupertinoDialogAction(
              child: const Text('Yes'),
              isDestructiveAction: true,
              onPressed: () {
                // Do something destructive.
              },
            )
          ],
        ),
      );
    },
    child: const Text('Delete all chat'),
  ),
)

輸出

9.新增 CupertinoDatePicker

CupertinoDatePicker 小元件允許使用者以標準的iOS風格挑選日期。

步驟:

  • 第 1 步:新增 CupertinoButton 小部件。
  • 第 2 步:在 onPressed 方法中,呼叫 _showDialog
  • 第 3 步:返回帶有一些有用引數的 CupertinoDatePicker 小部件,例如 initialDateTimemodeuse24hFormat
  • 第 4 步:新增 onDateTimeChanged 屬性並使用新日期rebuild小部件。

程式碼

Center(
  child: CupertinoButton(
    // Display a CupertinoDatePicker in date picker mode.
    onPressed: () => _showDialog(
      CupertinoDatePicker(
        backgroundColor: CupertinoColors.white,
        initialDateTime: date,
        mode: CupertinoDatePickerMode.date,
        use24hFormat: true,
        // This is called when the user changes the date.
        onDateTimeChanged: (DateTime newDate) {
          setState(() => date = newDate);
        },
      ),
    ),
    // In this example, the date value is formatted manually. You can use intl package
    // to format the value based on user's locale settings.
    child: Text(
      '${date.month}-${date.day}-${date.year}',
      style: const TextStyle(
        fontSize: 22.0,
      ),
    ),
  ),
)

輸出

你可以在這裡找到完整的原始碼。

原始碼:https://github.com/pinkeshdar...

相關文章