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)。我们下篇见!

相关推荐
vocal17 小时前
【我的AOSP第一课】AOSP 下载、编译与运行
android
Lei活在当下17 小时前
【业务场景架构实战】8. 订单状态流转在 UI 端的呈现设计
android·设计模式·架构
小趴菜822718 小时前
Android中加载unity aar包实现方案
android·unity·游戏引擎
qq_2529241918 小时前
PHP 8.0+ 现代Web开发实战指南 引
android·前端·php
Jeled18 小时前
Android 本地存储方案深度解析:SharedPreferences、DataStore、MMKV 全面对比
android·前端·缓存·kotlin·android studio·android jetpack
2501_915918411 天前
掌握 iOS 26 App 运行状况,多工具协作下的监控策略
android·ios·小程序·https·uni-app·iphone·webview
2501_915909061 天前
iOS 混淆实战,多工具组合完成 IPA 混淆与加固(源码 + 成品 + 运维一体化方案)
android·运维·ios·小程序·uni-app·iphone·webview
*才华有限公司*1 天前
安卓前后端连接教程
android