Flutter 系列教程:常用基础组件 (上) - `Text`, `Image`, `Icon`, `Button`

在构建任何用户界面时,都离不开文本、图片、图标和按钮这四大基本元素。它们是向用户展示信息、提供视觉引导和接收用户交互的核心。Flutter 提供了功能丰富且易于使用的组件来实现它们。

学习目标

  • 掌握 Text Widget,学会设置字体、颜色、对齐等多种样式。
  • 学会使用 Image Widget 从网络、本地资源和内存中加载图片。
  • 掌握 Icon Widget,并了解如何使用 Flutter 内置的 Material Design 图标库。
  • 全面了解 Flutter 中常用的按钮类型,如 ElevatedButtonTextButtonIconButton,并学会如何响应点击事件。

1. Text:显示文本

Text Widget 是我们用来在屏幕上显示字符串的组件。它看起来简单,但通过 style 属性,我们可以定制其外观的方方面面。

核心属性

  • data: 需要显示的字符串内容。
  • style (TextStyle ): 用于定义文本样式的对象,这是最重要的属性。
    • fontSize: 字体大小。
    • color: 字体颜色。
    • fontWeight: 字体粗细 (e.g., FontWeight.bold 加粗)。
    • fontStyle: 字体样式 (e.g., FontStyle.italic 斜体)。
    • decoration: 文本装饰 (e.g., TextDecoration.underline 下划线)。
    • fontFamily: 自定义字体(需要先在项目中配置)。
  • textAlign: 文本的对齐方式 (e.g., TextAlign.center 居中)。
  • maxLines: 文本显示的最大行数。
  • overflow: 当文本超出 maxLines 限制时的处理方式 (e.g., TextOverflow.ellipsis 显示省略号)。

代码示例:创建一个富文本标签

less 复制代码
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Text Widget Demo')),
        body: const Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'Hello, Flutter!',
                style: TextStyle(
                  fontSize: 32.0,
                  color: Colors.blue,
                  fontWeight: FontWeight.bold,
                  fontStyle: FontStyle.italic,
                  decoration: TextDecoration.underline,
                  decorationColor: Colors.red,
                  decorationStyle: TextDecorationStyle.wavy,
                ),
              ),
              SizedBox(height: 20),
              Text(
                '这是一个很长很长很长很长很长很长很长很长很长很长很长很长很长很长的文本,它会自动换行来适应空间。',
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 18),
              ),
              SizedBox(height: 20),
              Text(
                '这段文字如果太长了就会被截断并显示省略号,因为我们设置了最大行数为1。',
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
                style: TextStyle(fontSize: 18, color: Colors.grey),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

2. Image:显示图片

Image Widget 提供了多种构造函数来方便地从不同来源加载图片。

常用构造函数

  • Image.network(): 从网络 URL 加载图片。
  • Image.asset(): 从应用的本地资源文件夹 (assets) 加载图片。
  • Image.file(): 从用户手机上的具体文件路径加载图片。
  • Image.memory(): 从内存中的 Uint8List 数据加载图片。

使用本地资源 Image.asset() 的步骤

  1. 在你的项目根目录下创建一个 assets 文件夹 (通常会再建一个子文件夹如 assets/images/)。

  2. 将图片文件放入该文件夹。

  3. 打开项目根目录下的 pubspec.yaml 文件,找到 flutter: 部分,取消 assets: 的注释,并添加你的资源路径。

    yaml 复制代码
    flutter:
      assets:
        - assets/images/
  4. 现在你就可以在代码中使用 Image.asset('assets/images/your_image.png') 了。

核心属性

  • width, height: 图片的宽度和高度。
  • fit (BoxFit ): 图片的填充方式。
    • BoxFit.cover: 常用。按比例缩放,裁剪多余部分以完全覆盖容器。
    • BoxFit.contain: 按比例缩放,完整显示图片,可能会有留白。
    • BoxFit.fill: 不按比例缩放,拉伸以填满容器,图片可能会变形。
    • BoxFit.fitWidth/BoxFit.fitHeight: 按宽度/高度填满,另一边按比例缩放。

代码示例:加载网络和本地图片

less 复制代码
import 'package:flutter/material.dart';

// 确保你在 pubspec.yaml 中配置了 assets 路径!
// flutter:
//   assets:
//     - assets/images/

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Image Widget Demo')),
        body: SingleChildScrollView( // 使用可滚动视图防止内容溢出
          padding: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text('从网络加载图片 (Network Image):', style: TextStyle(fontSize: 18)),
              Container(
                width: 300,
                height: 200,
                margin: const EdgeInsets.symmetric(vertical: 10),
                decoration: BoxDecoration(border: Border.all()),
                child: Image.network(
                  'https://picsum.photos/300/200',
                  fit: BoxFit.cover,
                  // 添加加载中的占位符
                  loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
                    if (loadingProgress == null) return child;
                    return Center(
                      child: CircularProgressIndicator(
                        value: loadingProgress.expectedTotalBytes != null
                            ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
                            : null,
                      ),
                    );
                  },
                ),
              ),

              const Divider(),

              const Text('从本地资源加载图片 (Asset Image):', style: TextStyle(fontSize: 18)),
              Container(
                width: 150,
                height: 150,
                margin: const EdgeInsets.symmetric(vertical: 10),
                child: Image.asset(
                  'assets/images/flutter_logo.png', // 假设你的图片放在这个路径
                   // 如果图片不存在,可以显示一个错误占位符
                  errorBuilder: (context, error, stackTrace) {
                    return const Icon(Icons.error, color: Colors.red, size: 50);
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

注意 :你需要自己准备一张名为 flutter_logo.png 的图片并放到 assets/images/ 目录下才能让本地图片示例正常运行。


3. Icon:显示图标

Flutter 自带了一套非常丰富的 Material Design 图标,我们可以通过 Icon Widget 来使用它们。

核心属性

  • icon_data: 需要显示的图标,通常来自 Icons 类,例如 Icons.star
  • size: 图标的大小。
  • color: 图标的颜色。
dart 复制代码
Icon(
  Icons.favorite, // 图标
  color: Colors.pink,
  size: 30.0,
  semanticLabel: 'Text to announce in accessibility modes', // 辅助功能标签
)

4. Button:响应用户点击

按钮是应用交互的核心。Flutter 提供了多种设计风格的按钮来满足不同场景的需求。所有按钮都有一个共同的关键属性:onPressed

  • onPressed: 一个回调函数 (VoidCallback)。当用户点击按钮时,这个函数会被调用。如果 onPressed 被设置为 null,按钮将自动变为禁用状态

常用按钮类型

a) ElevatedButton (浮起按钮) 这是最常用的按钮类型,有一个背景色和一个轻微的阴影,看起来像是"浮"在界面上。

dart 复制代码
ElevatedButton(
  onPressed: () {
    print('ElevatedButton pressed!');
  },
  child: const Text('Elevated Button'),
)

b) TextButton (文本按钮) 没有背景色和阴影,看起来就像一个可点击的文本标签。通常用于次要操作。

dart 复制代码
TextButton(
  onPressed: () {
    print('TextButton pressed!');
  },
  child: const Text('Text Button'),
)

c) IconButton (图标按钮) 只包含一个图标的按钮,通常用于工具栏或需要节省空间的地方。

dart 复制代码
IconButton(
  icon: const Icon(Icons.thumb_up),
  onPressed: () {
    print('IconButton pressed!');
  },
  tooltip: 'Like', // 长按时显示的提示文字
)

d) OutlinedButton (轮廓按钮) 带有一个边框,但没有背景填充色。介于 ElevatedButtonTextButton 之间。

dart 复制代码
OutlinedButton(
  onPressed: () {
    print('OutlinedButton pressed!');
  },
  child: const Text('Outlined Button'),
)

完整演示代码

less 复制代码
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Basic Widgets Demo')),
        body: Center(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.stretch, // 让按钮宽度撑满
              children: <Widget>[
                // Text 和 Icon 结合
                const Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Icon(Icons.widgets, color: Colors.blue, size: 40),
                    SizedBox(width: 10),
                    Text('基础组件', style: TextStyle(fontSize: 28)),
                  ],
                ),
                
                const Divider(height: 40),

                // -- 按钮展示 --
                ElevatedButton(
                  onPressed: () {
                    print('Elevated Button Clicked');
                  },
                  style: ElevatedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(vertical: 12),
                  ),
                  child: const Text('ElevatedButton', style: TextStyle(fontSize: 18)),
                ),

                const SizedBox(height: 10),

                TextButton(
                  onPressed: () {
                    print('Text Button Clicked');
                  },
                  child: const Text('TextButton', style: TextStyle(fontSize: 18)),
                ),

                const SizedBox(height: 10),

                OutlinedButton(
                  onPressed: () {
                    print('Outlined Button Clicked');
                  },
                  style: OutlinedButton.styleFrom(
                     padding: const EdgeInsets.symmetric(vertical: 12),
                  ),
                  child: const Text('OutlinedButton', style: TextStyle(fontSize: 18)),
                ),
                
                 const SizedBox(height: 10),
                
                 // IconButton
                 Row(
                   mainAxisAlignment: MainAxisAlignment.center,
                   children: [
                     IconButton(
                       icon: const Icon(Icons.favorite),
                       iconSize: 30,
                       color: Colors.red,
                       onPressed: () {},
                     ),
                     IconButton(
                       icon: const Icon(Icons.share),
                       iconSize: 30,
                       color: Colors.green,
                       onPressed: null, // 设置为 null,按钮禁用
                     ),
                   ],
                 )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

总结

今天我们学习了构建 Flutter 界面的四大基础组件。

  • Text 用于显示和格式化文本。
  • Image 负责从各种来源加载和显示图片。
  • Icon 提供了丰富的矢量图标库。
  • 各种 Button (如 ElevatedButton, TextButton) 用于响应用户交互。

熟练掌握这些基础组件是构建任何美观且功能丰富的 Flutter 应用的第一步。在下一篇教程中,我们将学习如何处理用户输入,包括文本输入框 (TextField)、复选框 (Checkbox) 和开关 (Switch)。我们下篇见!

相关推荐
恋猫de小郭3 小时前
Fluttercon EU 2025 :Let's go far with Flutter
android·前端·flutter
诺诺Okami3 小时前
Android Framework- AMS 之 Activity-暂停
android
2501_915921433 小时前
TCP 抓包分析实战,从抓取到定位(命令、常见症状、排查流程与真机抓包补充)
网络·网络协议·tcp/ip·ios·小程序·uni-app·iphone
2501_916013743 小时前
App 上架服务全流程解析,iOS 应用代上架、ipa 文件上传工具、TestFlight 测试与苹果审核实战经验
android·ios·小程序·https·uni-app·iphone·webview
小李飞刀李寻欢4 小时前
flutter 详细解读
flutter
建群新人小猿4 小时前
客户标签自动管理:标签自动化运营,画像持久保鲜
android·java·大数据·前端·git
一直向钱5 小时前
android 自定义样式 Toast 实现(兼容 Android 4.1+~Android 16(API 16))
android
一直向钱5 小时前
android SharedPreferences 工具类 * 兼容 Android 16+ (API 16)
android
2501_915909065 小时前
App Store 上架完整流程解析,iOS 应用发布步骤、ipa 文件上传工具、TestFlight 测试与苹果审核经验
android·macos·ios·小程序·uni-app·cocoa·iphone