Skip to content
On this page

Flutter UI组件

Flutter提供了丰富的UI组件(Widgets)来构建美观、功能强大的用户界面。本章将详细介绍各种UI组件的使用方法、特性和最佳实践。

基础UI组件

文本组件

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

class TextComponentsDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Text Components')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 基础文本
            Text(
              '基础文本',
              style: TextStyle(fontSize: 16),
            ),
            SizedBox(height: 16),
            
            // 标题文本
            Text(
              '标题文本示例',
              style: Theme.of(context).textTheme.headlineSmall,
            ),
            SizedBox(height: 8),
            
            // 正文文本
            Text(
              '这是正文文本示例,通常用于描述性内容的展示。',
              style: Theme.of(context).textTheme.bodyMedium,
            ),
            SizedBox(height: 16),
            
            // 样式化文本
            Text(
              '粗体、斜体、下划线文本',
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
                fontStyle: FontStyle.italic,
                decoration: TextDecoration.underline,
                color: Colors.blue,
              ),
            ),
            SizedBox(height: 16),
            
            // 富文本
            RichText(
              text: TextSpan(
                style: TextStyle(color: Colors.black87, fontSize: 16),
                children: [
                  TextSpan(text: '富文本示例:'),
                  TextSpan(
                    text: '重要部分',
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                      color: Colors.red,
                    ),
                  ),
                  TextSpan(text: ' 普通部分'),
                  TextSpan(
                    text: ' 链接样式',
                    style: TextStyle(
                      color: Colors.blue,
                      decoration: TextDecoration.underline,
                    ),
                  ),
                ],
              ),
            ),
            SizedBox(height: 16),
            
            // 自适应文本
            Container(
              width: 200,
              child: Text(
                '这是一个很长的文本示例,用于演示文本溢出处理。当文本超出容器宽度时,会有不同的处理方式。',
                maxLines: 2,
                overflow: TextOverflow.ellipsis,
                style: TextStyle(fontSize: 14),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

按钮组件

dart
class ButtonComponentsDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Button Components')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          children: [
            // ElevatedButton (Material Design)
            ElevatedButton(
              onPressed: () {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('ElevatedButton pressed')),
                );
              },
              child: Text('Elevated Button'),
            ),
            SizedBox(height: 16),
            
            // OutlinedButton
            OutlinedButton(
              onPressed: () {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('OutlinedButton pressed')),
                );
              },
              child: Text('Outlined Button'),
            ),
            SizedBox(height: 16),
            
            // TextButton
            TextButton(
              onPressed: () {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('TextButton pressed')),
                );
              },
              child: Text('Text Button'),
            ),
            SizedBox(height: 16),
            
            // IconButton
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                IconButton(
                  onPressed: () {
                    print('Favorite button pressed');
                  },
                  icon: Icon(Icons.favorite),
                  color: Colors.red,
                ),
                IconButton(
                  onPressed: () {
                    print('Share button pressed');
                  },
                  icon: Icon(Icons.share),
                  color: Colors.blue,
                ),
                IconButton(
                  onPressed: () {
                    print('More button pressed');
                  },
                  icon: Icon(Icons.more_vert),
                ),
              ],
            ),
            SizedBox(height: 16),
            
            // FloatingActionButton
            FloatingActionButton(
              onPressed: () {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('FloatingActionButton pressed')),
                );
              },
              child: Icon(Icons.add),
              backgroundColor: Colors.green,
            ),
            SizedBox(height: 16),
            
            // 自定义样式的按钮
            Container(
              width: double.infinity,
              height: 50,
              child: ElevatedButton(
                onPressed: () {},
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.purple,
                  foregroundColor: Colors.white,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(25),
                  ),
                  shadowColor: Colors.purpleAccent,
                  elevation: 5,
                ),
                child: Text(
                  'Custom Styled Button',
                  style: TextStyle(fontSize: 16),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

图片组件

dart
class ImageComponentsDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Image Components')),
      body: SingleChildScrollView(
        child: Padding(
          padding: EdgeInsets.all(16.0),
          child: Column(
            children: [
              // 网络图片
              Container(
                height: 200,
                width: double.infinity,
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(12),
                  child: Image.network(
                    'https://via.placeholder.com/600x400/4A90E2/FFFFFF?text=Network+Image',
                    fit: BoxFit.cover,
                    loadingBuilder: (context, child, loadingProgress) {
                      if (loadingProgress == null) return child;
                      
                      return Container(
                        decoration: BoxDecoration(
                          color: Colors.grey[300],
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: Center(
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              CircularProgressIndicator(
                                value: loadingProgress.expectedTotalBytes != null
                                    ? loadingProgress.cumulativeBytesLoaded /
                                        loadingProgress.expectedTotalBytes!
                                    : null,
                              ),
                              SizedBox(height: 8),
                              Text('Loading...'),
                            ],
                          ),
                        ),
                      );
                    },
                    errorBuilder: (context, error, stackTrace) {
                      return Container(
                        decoration: BoxDecoration(
                          color: Colors.grey[300],
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: Icon(
                          Icons.error_outline,
                          size: 50,
                          color: Colors.red,
                        ),
                      );
                    },
                  ),
                ),
              ),
              SizedBox(height: 16),
              
              // 本地图片 (需要在pubspec.yaml中声明资源)
              /*
              Image.asset(
                'assets/images/sample_image.jpg',
                width: 200,
                height: 150,
                fit: BoxFit.cover,
              ),
              */
              
              // 圆形图片
              Container(
                width: 120,
                height: 120,
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  border: Border.all(color: Colors.blue, width: 3),
                ),
                child: ClipOval(
                  child: Image.network(
                    'https://via.placeholder.com/200x200/FF6B6B/FFFFFF?text=Avatar',
                    fit: BoxFit.cover,
                  ),
                ),
              ),
              SizedBox(height: 16),
              
              // 圆角矩形图片
              Container(
                width: 200,
                height: 150,
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(16),
                  image: DecorationImage(
                    image: NetworkImage(
                      'https://via.placeholder.com/400x300/50C878/FFFFFF?text=Rounded+Image',
                    ),
                    fit: BoxFit.cover,
                  ),
                ),
              ),
              SizedBox(height: 16),
              
              // 带遮罩的图片
              Stack(
                children: [
                  Container(
                    width: 300,
                    height: 200,
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(12),
                      image: DecorationImage(
                        image: NetworkImage(
                          'https://via.placeholder.com/600x400/9B59B6/FFFFFF?text=Masked+Image',
                        ),
                        fit: BoxFit.cover,
                      ),
                    ),
                  ),
                  Positioned(
                    bottom: 0,
                    left: 0,
                    right: 0,
                    child: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)),
                        gradient: LinearGradient(
                          begin: Alignment.topCenter,
                          end: Alignment.bottomCenter,
                          colors: [Colors.transparent, Colors.black54],
                        ),
                      ),
                      padding: EdgeInsets.all(16),
                      child: Text(
                        '图片标题',
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

表单组件

输入框组件

dart
class FormComponentsDemo extends StatefulWidget {
  @override
  _FormComponentsDemoState createState() => _FormComponentsDemoState();
}

class _FormComponentsDemoState extends State<FormComponentsDemo> {
  final _formKey = GlobalKey<FormState>();
  final _textEditingController = TextEditingController();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  
  bool _obscurePassword = true;
  String? _selectedOption;
  bool _checkboxValue = false;
  bool _switchValue = false;
  double _sliderValue = 50.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Form Components')),
      body: Form(
        key: _formKey,
        child: SingleChildScrollView(
          padding: EdgeInsets.all(16.0),
          child: Column(
            children: [
              // 基础文本输入框
              TextFormField(
                controller: _textEditingController,
                decoration: InputDecoration(
                  labelText: '姓名',
                  hintText: '请输入您的姓名',
                  prefixIcon: Icon(Icons.person),
                  border: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(12),
                  ),
                ),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return '姓名不能为空';
                  }
                  if (value.length < 2) {
                    return '姓名至少需要2个字符';
                  }
                  return null;
                },
              ),
              SizedBox(height: 16),
              
              // 邮箱输入框
              TextFormField(
                controller: _emailController,
                decoration: InputDecoration(
                  labelText: '邮箱',
                  hintText: 'example@email.com',
                  prefixIcon: Icon(Icons.email),
                  border: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(12),
                  ),
                ),
                keyboardType: TextInputType.emailAddress,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return '邮箱不能为空';
                  }
                  if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) {
                    return '请输入有效的邮箱地址';
                  }
                  return null;
                },
              ),
              SizedBox(height: 16),
              
              // 密码输入框
              TextFormField(
                controller: _passwordController,
                decoration: InputDecoration(
                  labelText: '密码',
                  hintText: '请输入密码',
                  prefixIcon: Icon(Icons.lock),
                  suffixIcon: IconButton(
                    icon: Icon(
                      _obscurePassword ? Icons.visibility : Icons.visibility_off,
                    ),
                    onPressed: () {
                      setState(() {
                        _obscurePassword = !_obscurePassword;
                      });
                    },
                  ),
                  border: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(12),
                  ),
                ),
                obscureText: _obscurePassword,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return '密码不能为空';
                  }
                  if (value.length < 6) {
                    return '密码至少需要6个字符';
                  }
                  return null;
                },
              ),
              SizedBox(height: 16),
              
              // 下拉选择框
              DropdownButtonFormField<String>(
                value: _selectedOption,
                decoration: InputDecoration(
                  labelText: '请选择选项',
                  border: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(12),
                  ),
                ),
                items: ['选项1', '选项2', '选项3', '选项4'].map((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList(),
                onChanged: (String? newValue) {
                  setState(() {
                    _selectedOption = newValue;
                  });
                },
                validator: (value) {
                  if (value == null) {
                    return '请选择一个选项';
                  }
                  return null;
                },
              ),
              SizedBox(height: 16),
              
              // 复选框
              Row(
                children: [
                  Checkbox(
                    value: _checkboxValue,
                    onChanged: (bool? value) {
                      setState(() {
                        _checkboxValue = value ?? false;
                      });
                    },
                  ),
                  Text('同意服务条款'),
                ],
              ),
              SizedBox(height: 16),
              
              // 开关
              Row(
                children: [
                  Text('推送通知'),
                  Spacer(),
                  Switch(
                    value: _switchValue,
                    onChanged: (bool value) {
                      setState(() {
                        _switchValue = value;
                      });
                    },
                  ),
                ],
              ),
              SizedBox(height: 16),
              
              // 滑块
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('音量控制: ${_sliderValue.toInt()}'),
                  Slider(
                    value: _sliderValue,
                    min: 0,
                    max: 100,
                    divisions: 10,
                    label: _sliderValue.round().toString(),
                    onChanged: (double value) {
                      setState(() {
                        _sliderValue = value;
                      });
                    },
                  ),
                ],
              ),
              SizedBox(height: 24),
              
              // 提交按钮
              SizedBox(
                width: double.infinity,
                height: 50,
                child: ElevatedButton(
                  onPressed: _submitForm,
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.blue,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(12),
                    ),
                  ),
                  child: Text(
                    '提交',
                    style: TextStyle(fontSize: 16, color: Colors.white),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _submitForm() {
    if (_formKey.currentState!.validate()) {
      // 显示表单数据
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('表单数据'),
            content: SingleChildScrollView(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text('姓名: ${_textEditingController.text}'),
                  Text('邮箱: ${_emailController.text}'),
                  Text('密码: ${'*' * _passwordController.text.length}'),
                  Text('选择: $_selectedOption'),
                  Text('复选框: $_checkboxValue'),
                  Text('开关: $_switchValue'),
                  Text('滑块: ${_sliderValue.toInt()}'),
                ],
              ),
            ),
            actions: [
              TextButton(
                onPressed: () => Navigator.of(context).pop(),
                child: Text('确定'),
              ),
            ],
          );
        },
      );
    }
  }

  @override
  void dispose() {
    _textEditingController.dispose();
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }
}

列表组件

ListView和ListTile

dart
class ListComponentsDemo extends StatefulWidget {
  @override
  _ListComponentsDemoState createState() => _ListComponentsDemoState();
}

class _ListComponentsDemoState extends State<ListComponentsDemo> {
  final List<Map<String, dynamic>> _items = [
    {
      'id': 1,
      'title': '项目 1',
      'subtitle': '这是第一个项目的描述',
      'icon': Icons.home,
      'color': Colors.blue,
    },
    {
      'id': 2,
      'title': '项目 2',
      'subtitle': '这是第二个项目的描述',
      'icon': Icons.favorite,
      'color': Colors.red,
    },
    {
      'id': 3,
      'title': '项目 3',
      'subtitle': '这是第三个项目的描述',
      'icon': Icons.settings,
      'color': Colors.green,
    },
    {
      'id': 4,
      'title': '项目 4',
      'subtitle': '这是第四个项目的描述',
      'icon': Icons.notifications,
      'color': Colors.orange,
    },
    {
      'id': 5,
      'title': '项目 5',
      'subtitle': '这是第五个项目的描述',
      'icon': Icons.person,
      'color': Colors.purple,
    },
  ];

  bool _showLeading = true;
  bool _showTrailing = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('List Components'),
        actions: [
          PopupMenuButton<String>(
            onSelected: (String value) {
              setState(() {
                if (value == 'toggle-leading') {
                  _showLeading = !_showLeading;
                } else if (value == 'toggle-trailing') {
                  _showTrailing = !_showTrailing;
                }
              });
            },
            itemBuilder: (BuildContext context) {
              return [
                PopupMenuItem(
                  value: 'toggle-leading',
                  child: Text(_showLeading ? '隐藏图标' : '显示图标'),
                ),
                PopupMenuItem(
                  value: 'toggle-trailing',
                  child: Text(_showTrailing ? '隐藏箭头' : '显示箭头'),
                ),
              ];
            },
          ),
        ],
      ),
      body: ListView.builder(
        itemCount: _items.length,
        itemBuilder: (context, index) {
          final item = _items[index];
          return Card(
            margin: EdgeInsets.symmetric(horizontal: 16, vertical: 4),
            child: ListTile(
              leading: _showLeading
                  ? CircleAvatar(
                      backgroundColor: item['color'],
                      child: Icon(item['icon'], color: Colors.white),
                    )
                  : null,
              title: Text(
                item['title'],
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              subtitle: Text(item['subtitle']),
              trailing: _showTrailing ? Icon(Icons.arrow_forward_ios, size: 16) : null,
              onTap: () {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('点击了 ${item['title']}')),
                );
              },
              onLongPress: () {
                showDialog(
                  context: context,
                  builder: (BuildContext context) {
                    return AlertDialog(
                      title: Text('确认删除'),
                      content: Text('确定要删除 ${item['title']} 吗?'),
                      actions: [
                        TextButton(
                          onPressed: () => Navigator.of(context).pop(),
                          child: Text('取消'),
                        ),
                        TextButton(
                          onPressed: () {
                            setState(() {
                              _items.removeAt(index);
                            });
                            Navigator.of(context).pop();
                            ScaffoldMessenger.of(context).showSnackBar(
                              SnackBar(content: Text('已删除 ${item['title']}')),
                            );
                          },
                          child: Text('删除', style: TextStyle(color: Colors.red)),
                        ),
                      ],
                    );
                  },
                );
              },
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _addItem,
        child: Icon(Icons.add),
      ),
    );
  }

  void _addItem() {
    setState(() {
      _items.add({
        'id': _items.length + 1,
        'title': '新项目 ${_items.length + 1}',
        'subtitle': '这是新添加项目的描述',
        'icon': Icons.new_releases,
        'color': Colors.teal,
      });
    });
  }
}

ExpansionTile

dart
class ExpansionTileDemo extends StatelessWidget {
  final List<Map<String, dynamic>> _categories = [
    {
      'title': '水果',
      'children': ['苹果', '香蕉', '橙子', '葡萄'],
      'icon': Icons.local_grocery_store,
    },
    {
      'title': '蔬菜',
      'children': ['胡萝卜', '西红柿', '黄瓜', '白菜'],
      'icon': Icons.eco,
    },
    {
      'title': '电子产品',
      'children': ['手机', '电脑', '平板', '耳机'],
      'icon': Icons.phone_android,
    },
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Expansion Tile Demo')),
      body: ListView.builder(
        itemCount: _categories.length,
        itemBuilder: (context, index) {
          final category = _categories[index];
          return Card(
            margin: EdgeInsets.symmetric(horizontal: 16, vertical: 4),
            child: ExpansionTile(
              leading: Icon(category['icon']),
              title: Text(
                category['title'],
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              children: category['children']
                  .map((child) => Padding(
                        padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                        child: Row(
                          children: [
                            Icon(Icons.circle, size: 8, color: Colors.grey),
                            SizedBox(width: 8),
                            Text(child),
                          ],
                        ),
                      ))
                  .toList(),
            ),
          );
        },
      ),
    );
  }
}

导航组件

BottomNavigationBar

dart
class BottomNavigationDemo extends StatefulWidget {
  @override
  _BottomNavigationDemoState createState() => _BottomNavigationDemoState();
}

class _BottomNavigationDemoState extends State<BottomNavigationDemo> {
  int _selectedIndex = 0;
  
  final List<Widget> _pages = [
    HomePage(),
    SearchPage(),
    ProfilePage(),
    SettingsPage(),
  ];

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: IndexedStack(
        index: _selectedIndex,
        children: _pages,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            activeIcon: Icon(Icons.home, color: Colors.blue),
            label: '首页',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            activeIcon: Icon(Icons.search, color: Colors.blue),
            label: '搜索',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            activeIcon: Icon(Icons.person, color: Colors.blue),
            label: '我的',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings),
            activeIcon: Icon(Icons.settings, color: Colors.blue),
            label: '设置',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.blue,
        unselectedItemColor: Colors.grey,
        onTap: _onItemTapped,
        type: BottomNavigationBarType.fixed,
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.home, size: 64, color: Colors.blue),
          SizedBox(height: 16),
          Text('首页', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
        ],
      ),
    );
  }
}

class SearchPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.search, size: 64, color: Colors.green),
          SizedBox(height: 16),
          Text('搜索', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
        ],
      ),
    );
  }
}

class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.person, size: 64, color: Colors.orange),
          SizedBox(height: 16),
          Text('我的', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
        ],
      ),
    );
  }
}

class SettingsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.settings, size: 64, color: Colors.purple),
          SizedBox(height: 16),
          Text('设置', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
        ],
      ),
    );
  }
}

AppBar和Drawer

dart
class NavigationDrawerDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Navigation with Drawer'),
        actions: [
          IconButton(
            icon: Icon(Icons.search),
            onPressed: () {
              print('Search button pressed');
            },
          ),
          IconButton(
            icon: Icon(Icons.more_vert),
            onPressed: () {
              print('More options pressed');
            },
          ),
        ],
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            DrawerHeader(
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  CircleAvatar(
                    radius: 30,
                    backgroundColor: Colors.white,
                    child: Icon(Icons.person, size: 30, color: Colors.blue),
                  ),
                  SizedBox(height: 8),
                  Text(
                    '用户名',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  Text(
                    'user@example.com',
                    style: TextStyle(
                      color: Colors.white70,
                      fontSize: 14,
                    ),
                  ),
                ],
              ),
            ),
            ListTile(
              leading: Icon(Icons.home),
              title: Text('首页'),
              onTap: () {
                Navigator.pop(context);
                // 处理导航
              },
            ),
            ListTile(
              leading: Icon(Icons.favorite),
              title: Text('收藏'),
              onTap: () {
                Navigator.pop(context);
                // 处理导航
              },
            ),
            ListTile(
              leading: Icon(Icons.history),
              title: Text('历史记录'),
              onTap: () {
                Navigator.pop(context);
                // 处理导航
              },
            ),
            Divider(),
            ListTile(
              leading: Icon(Icons.settings),
              title: Text('设置'),
              onTap: () {
                Navigator.pop(context);
                // 处理导航
              },
            ),
            ListTile(
              leading: Icon(Icons.help),
              title: Text('帮助'),
              onTap: () {
                Navigator.pop(context);
                // 处理导航
              },
            ),
          ],
        ),
      ),
      body: Center(
        child: Text('主内容区域'),
      ),
    );
  }
}

对话框组件

AlertDialog和SnackBar

dart
class DialogComponentsDemo extends StatefulWidget {
  @override
  _DialogComponentsDemoState createState() => _DialogComponentsDemoState();
}

class _DialogComponentsDemoState extends State<DialogComponentsDemo> {
  final GlobalKey<ScaffoldMessengerState> _scaffoldKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return ScaffoldMessenger(
      key: _scaffoldKey,
      child: Scaffold(
        appBar: AppBar(title: Text('Dialog Components')),
        body: Padding(
          padding: EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton(
                onPressed: _showAlertDialog,
                child: Text('显示确认对话框'),
              ),
              ElevatedButton(
                onPressed: _showCustomDialog,
                child: Text('显示自定义对话框'),
              ),
              ElevatedButton(
                onPressed: _showSnackBar,
                child: Text('显示Snack Bar'),
              ),
              ElevatedButton(
                onPressed: _showBottomSheet,
                child: Text('显示底部面板'),
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _showAlertDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('确认操作'),
          content: Text('您确定要执行此操作吗?此操作不可逆。'),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(context).pop(false),
              child: Text('取消'),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.of(context).pop(true);
                _showSnackBar();
              },
              child: Text('确定'),
            ),
          ],
        );
      },
    );
  }

  void _showCustomDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return Dialog(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16),
          ),
          child: Container(
            padding: EdgeInsets.all(16),
            constraints: BoxConstraints(minHeight: 200, minWidth: 300),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Icon(
                  Icons.star,
                  size: 48,
                  color: Colors.orange,
                ),
                SizedBox(height: 16),
                Text(
                  '自定义对话框',
                  style: TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                SizedBox(height: 8),
                Text(
                  '这是一个自定义样式的对话框示例',
                  textAlign: TextAlign.center,
                ),
                SizedBox(height: 16),
                Row(
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: [
                    TextButton(
                      onPressed: () => Navigator.of(context).pop(),
                      child: Text('关闭'),
                    ),
                  ],
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  void _showSnackBar() {
    _scaffoldKey.currentState?.showSnackBar(
      SnackBar(
        content: Text('这是一个 SnackBar 消息'),
        action: SnackBarAction(
          label: '撤销',
          onPressed: () {
            print('撤销操作');
          },
        ),
        duration: Duration(seconds: 3),
      ),
    );
  }

  void _showBottomSheet() {
    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      builder: (BuildContext context) {
        return Container(
          padding: EdgeInsets.all(16),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Container(
                width: 40,
                height: 4,
                decoration: BoxDecoration(
                  color: Colors.grey[300],
                  borderRadius: BorderRadius.circular(2),
                ),
              ),
              SizedBox(height: 16),
              Text(
                '底部面板',
                style: TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                ),
              ),
              SizedBox(height: 16),
              ListTile(
                leading: Icon(Icons.share),
                title: Text('分享'),
                onTap: () {
                  Navigator.pop(context);
                  _showSnackBar();
                },
              ),
              ListTile(
                leading: Icon(Icons.favorite),
                title: Text('收藏'),
                onTap: () {
                  Navigator.pop(context);
                  _showSnackBar();
                },
              ),
              ListTile(
                leading: Icon(Icons.settings),
                title: Text('设置'),
                onTap: () {
                  Navigator.pop(context);
                  _showSnackBar();
                },
              ),
            ],
          ),
        );
      },
    );
  }
}

状态指示器组件

ProgressIndicator

dart
class ProgressIndicatorDemo extends StatefulWidget {
  @override
  _ProgressIndicatorDemoState createState() => _ProgressIndicatorDemoState();
}

class _ProgressIndicatorDemoState extends State<ProgressIndicatorDemo> {
  double _progressValue = 0.0;
  bool _isLoading = false;

  void _simulateProgress() {
    setState(() {
      _isLoading = true;
      _progressValue = 0.0;
    });

    Timer.periodic(Duration(milliseconds: 100), (timer) {
      if (_progressValue >= 1.0) {
        timer.cancel();
        setState(() {
          _isLoading = false;
        });
      } else {
        setState(() {
          _progressValue += 0.05;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Progress Indicators')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            // Linear Progress Indicator
            Column(
              children: [
                Text('Linear Progress'),
                SizedBox(height: 8),
                LinearProgressIndicator(
                  value: _isLoading ? _progressValue : null,
                  minHeight: 8,
                  borderRadius: BorderRadius.circular(4),
                ),
                SizedBox(height: 8),
                Text('${(_progressValue * 100).round()}%'),
              ],
            ),
            
            // Circular Progress Indicator
            Column(
              children: [
                Text('Circular Progress'),
                SizedBox(height: 8),
                SizedBox(
                  width: 60,
                  height: 60,
                  child: CircularProgressIndicator(
                    value: _isLoading ? _progressValue : null,
                    strokeWidth: 6,
                  ),
                ),
                SizedBox(height: 8),
                Text(_isLoading ? '加载中...' : '已完成'),
              ],
            ),
            
            // Custom Progress Indicator
            Column(
              children: [
                Text('Custom Progress'),
                SizedBox(height: 8),
                Container(
                  width: 200,
                  height: 20,
                  decoration: BoxDecoration(
                    color: Colors.grey[300],
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(10),
                    child: LinearProgressIndicator(
                      value: _progressValue,
                      backgroundColor: Colors.transparent,
                      valueColor: AlwaysStoppedAnimation<Color>(Colors.green),
                    ),
                  ),
                ),
              ],
            ),
            
            ElevatedButton(
              onPressed: _simulateProgress,
              child: Text('开始模拟进度'),
            ),
          ],
        ),
      ),
    );
  }
}

总结

Flutter提供了丰富的UI组件,从基础的文本、按钮、图片到复杂的表单、列表、导航组件。合理使用这些组件可以构建出功能丰富、用户体验良好的应用程序。在实际开发中,应该根据具体需求选择合适的组件,并注意组件的性能和用户体验。