头图

Flutter Cupertino 教程:如何构建外观和感觉原生的 iOS 应用

杭州程序员张张
English

所有前端应用程序都使用某种设计系统来帮助用户更轻松地完成任务。他们可能会使用内部开发的定制设计系统或成熟的设计系统,例如 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...
阅读 2.6k

前端全栈开发者
专栏首发于公众号《前端全栈开发者》,订阅关注第一时间阅读好文

Web/Flutter/独立开发者/铲屎官

11.7k 声望
6.6k 粉丝
0 条评论

Web/Flutter/独立开发者/铲屎官

11.7k 声望
6.6k 粉丝
宣传栏