MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

探索flutter中的material和cupertino组件库

2021-10-193.9k 阅读

Flutter 中的 Material 组件库

Material 设计理念

Material Design 是由 Google 推出的一套视觉设计语言,旨在为不同平台和设备提供一致且直观的用户体验。它借鉴了现实世界中的物理规律,如光影、材质和空间关系,创造出具有立体感和动态效果的界面。在 Flutter 中,Material 组件库就是基于这种设计理念构建的,它提供了一系列符合 Material Design 规范的 UI 组件,帮助开发者快速搭建出美观、实用且易于交互的应用界面。

基础组件

  1. AppBar
    • 功能与特点:AppBar 是应用栏,通常位于屏幕顶部,用于显示应用的标题、导航按钮和其他重要操作。它是应用界面的重要组成部分,为用户提供了导航和操作的入口。
    • 代码示例
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 App'),
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.search),
              onPressed: () {},
            )
          ],
        ),
        body: Center(
          child: Text('Content'),
        ),
      ),
    );
  }
}
  • 解析:在上述代码中,通过 AppBar 类创建了一个应用栏。title 属性设置了应用栏的标题为 “My App”。actions 列表中添加了一个搜索图标按钮,当用户点击该按钮时,会触发 onPressed 回调函数(这里暂时为空)。
  1. Button
    • 功能与特点:Flutter 中的按钮组件是用户与应用进行交互的重要元素。Material 组件库提供了多种类型的按钮,如 ElevatedButton(凸起按钮)、TextButton(文本按钮)和 OutlinedButton(轮廓按钮),每种按钮都有其独特的视觉风格和适用场景。
    • 代码示例
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: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ElevatedButton(
                onPressed: () {},
                child: Text('Elevated Button'),
              ),
              TextButton(
                onPressed: () {},
                child: Text('Text Button'),
              ),
              OutlinedButton(
                onPressed: () {},
                child: Text('Outlined Button'),
              )
            ],
          ),
        ),
      ),
    );
  }
}
  • 解析:这段代码展示了三种不同类型按钮的创建。ElevatedButton 具有凸起的效果,通常用于强调重要的操作;TextButton 只有文本,比较简洁,适用于不太突出的操作;OutlinedButton 有轮廓,视觉效果介于两者之间。每个按钮的 onPressed 属性指定了按钮点击时执行的逻辑(这里暂时为空),child 属性设置了按钮显示的文本。
  1. Card
    • 功能与特点:Card 组件用于在应用中展示相关信息的集合,它模拟了现实世界中卡片的外观,具有一定的阴影和圆角,使信息呈现更加清晰和美观。Card 可以包含各种其他组件,如文本、图片等。
    • 代码示例
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: Card(
            child: Column(
              children: <Widget>[
                Image.network(
                  'https://picsum.photos/200/300',
                  fit: BoxFit.cover,
                ),
                Padding(
                  padding: EdgeInsets.all(16.0),
                  child: Text(
                    'This is a card with an image and text.',
                    style: TextStyle(fontSize: 18.0),
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}
  • 解析:在这个示例中,Card 组件内部包含一个 ColumnColumn 又包含一个通过网络加载的图片和一段文本。Image.network 用于从指定的 URL 加载图片,Padding 组件用于给文本添加内边距,使文本看起来不那么贴近卡片边缘。

布局组件

  1. Row 和 Column
    • 功能与特点RowColumn 是 Flutter 中最常用的线性布局组件。Row 会将其子组件沿水平方向排列,Column 则沿垂直方向排列。它们提供了灵活的布局控制选项,如主轴和交叉轴的对齐方式等。
    • 代码示例
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                Container(
                  width: 100,
                  height: 100,
                  color: Colors.red,
                ),
                Container(
                  width: 100,
                  height: 100,
                  color: Colors.green,
                )
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                Container(
                  width: 100,
                  height: 100,
                  color: Colors.blue,
                ),
                Container(
                  width: 100,
                  height: 100,
                  color: Colors.yellow,
                )
              ],
            )
          ],
        ),
      ),
    );
  }
}
  • 解析:代码中使用了 Column 作为根布局,在 Column 内部有两个 Row。第一个 Row 使用 MainAxisAlignment.spaceEvenly 使两个红色和绿色的 Container 组件在水平方向上均匀分布。第二个 Row 使用 MainAxisAlignment.spaceAround,使蓝色和黄色的 Container 组件在水平方向上分布,并且周围有均匀的空白空间。
  1. Expanded
    • 功能与特点Expanded 组件通常用于 RowColumn 内部,它可以让其子组件在主轴方向上扩展,以填充剩余的空间。这在需要灵活分配空间时非常有用。
    • 代码示例
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Row(
          children: <Widget>[
            Expanded(
              flex: 1,
              child: Container(
                color: Colors.red,
              ),
            ),
            Expanded(
              flex: 2,
              child: Container(
                color: Colors.green,
              ),
            )
          ],
        ),
      ),
    );
  }
}
  • 解析:在这个 Row 布局中,有两个 Expanded 包裹的 Containerflex 属性用于指定扩展比例,这里红色 Containerflex 为 1,绿色 Containerflex 为 2,所以绿色 Container 会占据两倍于红色 Container 的水平空间。

高级组件

  1. TabBar 和 TabBarView
    • 功能与特点TabBarTabBarView 结合使用可以实现选项卡式的界面,用户可以通过切换选项卡来查看不同的内容。TabBar 用于显示选项卡标题,TabBarView 用于显示与每个选项卡对应的内容。
    • 代码示例
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            bottom: TabBar(
              tabs: <Widget>[
                Tab(text: 'Tab 1'),
                Tab(text: 'Tab 2'),
                Tab(text: 'Tab 3'),
              ],
            ),
            title: Text('Tab Example'),
          ),
          body: TabBarView(
            children: <Widget>[
              Center(child: Text('Content of Tab 1')),
              Center(child: Text('Content of Tab 2')),
              Center(child: Text('Content of Tab 3')),
            ],
          ),
        ),
      ),
    );
  }
}
  • 解析:通过 DefaultTabController 来管理选项卡的状态,length 属性指定了选项卡的数量为 3。AppBarbottom 属性设置为 TabBar,其中定义了三个选项卡标题。body 部分使用 TabBarView,其 children 列表对应每个选项卡的具体内容。
  1. BottomNavigationBar
    • 功能与特点BottomNavigationBar 通常位于屏幕底部,用于在应用的主要功能页面之间进行快速切换。它提供了简洁直观的导航方式,提升用户体验。
    • 代码示例
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        bottomNavigationBar: BottomNavigationBar(
          items: <BottomNavigationBarItem>[
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              label: 'Home',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.search),
              label: 'Search',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.person),
              label: 'Profile',
            )
          ],
          currentIndex: 0,
          onTap: (int index) {
            // 处理选项卡切换逻辑
          },
        ),
        body: Center(
          child: Text('Home Page'),
        ),
      ),
    );
  }
}
  • 解析:在这段代码中,BottomNavigationBar 包含三个 BottomNavigationBarItem,分别代表 “Home”、“Search” 和 “Profile”。currentIndex 属性指定了当前选中的选项卡索引,onTap 回调函数用于处理用户点击选项卡时的逻辑(这里暂时为空)。

Flutter 中的 Cupertino 组件库

Cupertino 设计理念

Cupertino 设计风格源自苹果的 iOS 系统,它强调简洁、直观和与设备的自然交互。与 Material Design 不同,Cupertino 更注重拟物化的设计元素,以提供用户熟悉的 iOS 风格体验。在 Flutter 中,Cupertino 组件库就是按照这种设计理念构建的,让开发者能够为 iOS 平台创建原生风格的应用界面。

基础组件

  1. CupertinoNavigationBar
    • 功能与特点CupertinoNavigationBar 类似于 iOS 应用中的导航栏,位于屏幕顶部,用于显示标题和导航按钮。它具有典型的 iOS 风格,如左侧的返回按钮和右侧的操作按钮。
    • 代码示例
import 'package:flutter/cupertino.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoPageScaffold(
        navigationBar: CupertinoNavigationBar(
          middle: Text('My Cupertino App'),
          trailing: CupertinoButton(
            child: Text('Edit'),
            onPressed: () {},
          ),
        ),
        child: Center(
          child: Text('Content'),
        ),
      ),
    );
  }
}
  • 解析:在这个示例中,通过 CupertinoNavigationBar 创建了一个导航栏。middle 属性设置了导航栏的中间标题为 “My Cupertino App”。trailing 属性添加了一个 “Edit” 按钮,点击按钮会触发 onPressed 回调函数(这里暂时为空)。
  1. CupertinoButton
    • 功能与特点CupertinoButton 是 Cupertino 风格的按钮组件,它具有与 iOS 系统按钮相似的外观和交互效果。根据不同的使用场景,有多种样式可供选择,如填充按钮、边框按钮等。
    • 代码示例
import 'package:flutter/cupertino.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoPageScaffold(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              CupertinoButton(
                child: Text('Filled Button'),
                onPressed: () {},
                color: CupertinoColors.activeBlue,
              ),
              CupertinoButton(
                child: Text('Bordered Button'),
                onPressed: () {},
                color: CupertinoColors.systemGrey,
                padding: EdgeInsets.all(16.0),
                borderRadius: BorderRadius.circular(8.0),
                border: Border.all(color: CupertinoColors.systemGrey),
              )
            ],
          ),
        ),
      ),
    );
  }
}
  • 解析:代码展示了两种 CupertinoButton 的创建。第一个按钮是填充按钮,通过 color 属性设置为蓝色。第二个按钮是边框按钮,通过 border 属性设置了边框,paddingborderRadius 属性调整了按钮的外观。每个按钮的 onPressed 属性指定了点击时的逻辑(这里暂时为空)。
  1. CupertinoAlertDialog
    • 功能与特点CupertinoAlertDialog 用于显示模态对话框,向用户传达重要信息或请求确认操作。它具有典型的 iOS 风格的外观和动画效果。
    • 代码示例
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoPageScaffold(
        child: Center(
          child: CupertinoButton(
            child: Text('Show Dialog'),
            onPressed: () {
              showCupertinoDialog(
                context: context,
                builder: (BuildContext context) {
                  return CupertinoAlertDialog(
                    title: Text('Alert'),
                    content: Text('This is a Cupertino alert dialog.'),
                    actions: <Widget>[
                      CupertinoDialogAction(
                        child: Text('Cancel'),
                        onPressed: () {
                          Navigator.pop(context);
                        },
                      ),
                      CupertinoDialogAction(
                        child: Text('OK'),
                        onPressed: () {
                          Navigator.pop(context);
                        },
                      )
                    ],
                  );
                },
              );
            },
          ),
        ),
      ),
    );
  }
}
  • 解析:在这个示例中,点击 “Show Dialog” 按钮会触发 showCupertinoDialog 函数。CupertinoAlertDialog 包含标题 “Alert”、内容 “This is a Cupertino alert dialog.” 以及两个按钮 “Cancel” 和 “OK”。点击按钮时,通过 Navigator.pop(context) 关闭对话框。

布局组件

  1. CupertinoPageScaffold
    • 功能与特点CupertinoPageScaffold 是 Cupertino 风格应用页面的基本脚手架,它提供了一个标准的页面布局结构,包括导航栏(如果有)和内容区域。
    • 代码示例
import 'package:flutter/cupertino.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoPageScaffold(
        navigationBar: CupertinoNavigationBar(
          middle: Text('Page Title'),
        ),
        child: Center(
          child: Text('Page Content'),
        ),
      ),
    );
  }
}
  • 解析:上述代码使用 CupertinoPageScaffold 创建了一个页面,navigationBar 属性设置了页面的导航栏标题为 “Page Title”,child 属性设置了页面的主要内容为 “Page Content”。
  1. CupertinoListTile
    • 功能与特点CupertinoListTile 用于在列表中显示单个项目,它具有简洁的 iOS 风格设计,可包含图标、文本和辅助信息等。
    • 代码示例
import 'package:flutter/cupertino.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoPageScaffold(
        child: CupertinoListTile(
          leading: Icon(CupertinoIcons.home),
          title: Text('Home'),
          subtitle: Text('Go to home page'),
          onTap: () {},
        ),
      ),
    );
  }
}
  • 解析:在这个例子中,CupertinoListTileleading 属性添加了一个房屋图标,title 设置了主文本为 “Home”,subtitle 设置了副标题为 “Go to home page”。onTap 属性指定了点击列表项时的逻辑(这里暂时为空)。

高级组件

  1. CupertinoTabBar 和 CupertinoTabScaffold
    • 功能与特点CupertinoTabBarCupertinoTabScaffold 配合使用可实现类似于 iOS 底部选项卡的导航效果。CupertinoTabBar 显示在屏幕底部,用于切换不同的选项卡页面,CupertinoTabScaffold 管理选项卡页面的内容。
    • 代码示例
import 'package:flutter/cupertino.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoTabScaffold(
        tabBar: CupertinoTabBar(
          items: <BottomNavigationBarItem>[
            BottomNavigationBarItem(
              icon: Icon(CupertinoIcons.home),
              label: 'Home',
            ),
            BottomNavigationBarItem(
              icon: Icon(CupertinoIcons.search),
              label: 'Search',
            ),
            BottomNavigationBarItem(
              icon: Icon(CupertinoIcons.person),
              label: 'Profile',
            )
          ],
        ),
        tabBuilder: (BuildContext context, int index) {
          switch (index) {
            case 0:
              return CupertinoPageScaffold(
                child: Center(
                  child: Text('Home Page'),
                ),
              );
            case 1:
              return CupertinoPageScaffold(
                child: Center(
                  child: Text('Search Page'),
                ),
              );
            case 2:
              return CupertinoPageScaffold(
                child: Center(
                  child: Text('Profile Page'),
                ),
              );
            default:
              return CupertinoPageScaffold();
          }
        },
      ),
    );
  }
}
  • 解析CupertinoTabBar 定义了三个底部选项卡,分别对应 “Home”、“Search” 和 “Profile”。tabBuilder 回调函数根据选项卡的索引返回相应的页面内容。当用户点击不同的选项卡时,会显示对应的 CupertinoPageScaffold 页面。
  1. CupertinoDatePicker
    • 功能与特点CupertinoDatePicker 是用于选择日期和时间的组件,它具有 iOS 风格的滚轮式交互界面,方便用户快速选择所需的日期和时间。
    • 代码示例
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoPageScaffold(
        child: Center(
          child: CupertinoButton(
            child: Text('Select Date'),
            onPressed: () {
              showCupertinoModalPopup(
                context: context,
                builder: (BuildContext context) {
                  return Container(
                    height: 216.0,
                    color: CupertinoColors.white,
                    child: CupertinoDatePicker(
                      initialDateTime: DateTime.now(),
                      minimumDate: DateTime(2000),
                      maximumDate: DateTime(2030),
                      onDateTimeChanged: (DateTime newDateTime) {
                        print('Selected date: $newDateTime');
                      },
                    ),
                  );
                },
              );
            },
          ),
        ),
      ),
    );
  }
}
  • 解析:点击 “Select Date” 按钮会弹出一个模态对话框,其中包含 CupertinoDatePickerinitialDateTime 设置了初始显示的日期和时间为当前时间,minimumDatemaximumDate 限定了可选日期的范围。onDateTimeChanged 回调函数在用户选择新的日期和时间时被触发,并打印出选中的日期。

Material 与 Cupertino 组件库的对比与选择

视觉风格

  1. Material Design:Material Design 强调简洁、扁平且富有现代感的设计,通过光影、材质和动画效果营造出一种立体感和动态性。其颜色体系丰富且鲜明,组件的形状通常较为规整,如矩形按钮、卡片等。
  2. Cupertino Design:Cupertino 设计风格源自 iOS,更注重拟物化元素,追求与 iOS 设备原生界面的一致性。颜色相对柔和,组件形状和交互方式更符合用户对 iOS 设备的操作习惯,如圆形按钮、滚轮式选择器等。

交互体验

  1. Material Design:提供了丰富的动画和过渡效果,使界面交互更加流畅和生动。例如,按钮点击时的涟漪效果,页面切换时的转场动画等。这些动画效果不仅增强了用户体验,还符合 Material Design 的设计理念。
  2. Cupertino Design:交互体验注重与 iOS 设备的自然交互,强调简洁和直观。例如,CupertinoDatePicker 的滚轮式选择方式,用户可以通过上下滑动滚轮轻松选择日期和时间,这种交互方式在 iOS 设备上非常常见且易于操作。

平台适配性

  1. Material Design:最初由 Google 推出,在 Android 平台上具有原生的支持和良好的适配性。但由于其设计理念的通用性,也可以很好地应用于 iOS 和其他平台,为跨平台应用提供统一的视觉风格。
  2. Cupertino Design:专门为 iOS 平台设计,与 iOS 系统的交互和视觉风格高度契合。在 iOS 应用开发中使用 Cupertino 组件库可以提供原生的用户体验,使应用看起来和操作起来都更像 iOS 原生应用。

如何选择

  1. 跨平台应用:如果开发的是跨平台应用,希望在不同平台上保持统一的视觉风格,那么 Material 组件库是一个不错的选择。它可以在 Android、iOS 和 Web 等平台上提供一致的体验,减少开发和维护成本。
  2. iOS 原生风格应用:如果目标是开发一款具有 iOS 原生风格的应用,为 iOS 用户提供熟悉的操作体验,那么 Cupertino 组件库是首选。它能够精准地模拟 iOS 系统的界面和交互,提升用户对应用的认同感。
  3. 混合使用:在某些情况下,也可以根据具体需求在应用中混合使用 Material 和 Cupertino 组件库。例如,对于一些通用的基础组件可以使用 Material 组件库,而对于特定的 iOS 功能模块(如日期选择器)则使用 Cupertino 组件库,以达到最佳的用户体验和开发效率。

在实际开发中,开发者应根据应用的目标平台、用户群体以及设计需求等因素综合考虑,选择合适的组件库来构建高质量的 Flutter 应用界面。无论是 Material 还是 Cupertino 组件库,都为 Flutter 开发者提供了强大的工具,帮助他们打造出优秀的用户界面。