Flutter之Widget体系与布局原理

发布于:2025-07-25 ⋅ 阅读:(12) ⋅ 点赞:(0)

第3章:Widget体系与布局原理

3.1 Widget树的构建与渲染机制

3.1.1 Flutter渲染流水线解析

Flutter的渲染系统是其高性能的核心所在。理解渲染机制对于优化应用性能至关重要。

// Flutter渲染流水线的三棵树结构示例
class RenderingPipelineDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Widget Tree - 配置信息
    return Scaffold(
      appBar: AppBar(title: Text('渲染流水线演示')),
      body: Container(  // Widget节点
        padding: EdgeInsets.all(16.0),
        child: Column(
          children: [
            Text('Hello Flutter'),  // Widget节点
            ElevatedButton(
              onPressed: () {},
              child: Text('点击按钮'),
            ),
          ],
        ),
      ),
    );
  }
}

// Element Tree对应的概念示例
/*
Widget Tree          Element Tree            RenderObject Tree
-----------         --------------          -------------------
Scaffold       →    ScaffoldElement    →    RenderScaffold
├─AppBar       →    ├─AppBarElement    →    ├─RenderAppBar
└─Container    →    └─ContainerElement →    └─RenderContainer
  └─Column     →      └─ColumnElement  →      └─RenderFlex
    ├─Text     →        ├─TextElement   →        ├─RenderParagraph
    └─Button   →        └─ButtonElement →        └─RenderButton
*/

3.1.2 Widget树的构建过程

// 演示Widget树构建的详细过程
class WidgetTreeBuildDemo extends StatefulWidget {
  @override
  _WidgetTreeBuildDemoState createState() => _WidgetTreeBuildDemoState();
}

class _WidgetTreeBuildDemoState extends State<WidgetTreeBuildDemo> {
  int _counter = 0;
  
  @override
  Widget build(BuildContext context) {
    print('🔄 build方法被调用 - counter: $_counter');
    
    return Scaffold(
      appBar: AppBar(
        title: Text('Widget树构建演示'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 每次build都会创建新的Text Widget
            Text(
              '计数器值:$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            SizedBox(height: 20),
            // 但Element树和RenderObject树会被复用
            ElevatedButton(
              onPressed: _incrementCounter,
              child: Text('增加计数'),
            ),
          ],
        ),
      ),
    );
  }
  
  void _incrementCounter() {
    setState(() {
      _counter++;
      // setState触发Widget树重建,但Element树只会更新必要部分
    });
  }
  
  @override
  void dispose() {
    print('🗑️ Widget被销毁');
    super.dispose();
  }
}

3.1.3 渲染性能优化原理

// 性能优化的最佳实践
class PerformanceOptimizedWidget extends StatefulWidget {
  @override
  _PerformanceOptimizedWidgetState createState() => 
      _PerformanceOptimizedWidgetState();
}

class _PerformanceOptimizedWidgetState extends State<PerformanceOptimizedWidget> {
  int _counter = 0;
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('性能优化演示')),
      body: Column(
        children: [
          // ❌ 错误做法:每次build都创建新的expensive widget
          // ExpensiveWidget(),
          
          // ✅ 正确做法1:提取为常量
          const ExpensiveStaticWidget(),
          
          // ✅ 正确做法2:使用const构造函数
          const Padding(
            padding: EdgeInsets.all(16.0),
            child: Text('这是一个常量Widget'),
          ),
          
          // ✅ 正确做法3:条件性重建
          CounterDisplay(counter: _counter),
          
          // ✅ 正确做法4:使用Builder减少重建范围
          Builder(
            builder: (context) => ElevatedButton(
              onPressed: () => setState(() => _counter++),
              child: Text('增加计数'),
            ),
          ),
        ],
      ),
    );
  }
}

// 独立的计数器显示组件,只有当counter改变时才重建
class CounterDisplay extends StatelessWidget {
  final int counter;
  
  const CounterDisplay({Key? key, required this.counter}) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    print('🔄 CounterDisplay重建 - counter: $counter');
    return Container(
      padding: EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.blue[100],
        borderRadius: BorderRadius.circular(8),
      ),
      child: Text(
        '当前计数:$counter',
        style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
      ),
    );
  }
}

// 昂贵的静态Widget - 使用const避免重建
class ExpensiveStaticWidget extends StatelessWidget {
  const ExpensiveStaticWidget({Key? key}) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    print('💰 ExpensiveStaticWidget被构建(应该只出现一次)');
    return Container(
      height: 200,
      child: ListView.builder(
        itemCount: 100,
        itemBuilder: (context, index) => ListTile(
          title: Text('静态项目 $index'),
        ),
      ),
    );
  }
}

3.2 StatelessWidget与StatefulWidget详解

3.2.1 StatelessWidget深入理解

// StatelessWidget的完整实现示例
class CustomStatelessWidget extends StatelessWidget {
  final String title;
  final Color backgroundColor;
  final VoidCallback? onTap;
  
  // 构造函数 - 所有属性都应该是final
  const CustomStatelessWidget({
    Key? key,
    required this.title,
    this.backgroundColor = Colors.blue,
    this.onTap,
  }) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    // build方法是纯函数,相同输入总是产生相同输出
    return GestureDetector(
      onTap: onTap,
      child: Container(
        padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
        decoration: BoxDecoration(
          color: backgroundColor,
          borderRadius: BorderRadius.circular(8),
          boxShadow: [
            BoxShadow(
              color: Colors.black26,
              blurRadius: 4,
              offset: Offset(0, 2),
            ),
          ],
        ),
        child: Text(
          title,
          style: TextStyle(
            color: Colors.white,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    );
  }
  
  // 重写操作符以支持比较
  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is CustomStatelessWidget &&
          runtimeType == other.runtimeType &&
          title == other.title &&
          backgroundColor == other.backgroundColor;
  
  @override
  int get hashCode => title.hashCode ^ backgroundColor.hashCode;
}

// StatelessWidget的最佳实践示例
class UserProfileCard extends StatelessWidget {
  final User user;
  final VoidCallback? onEdit;
  
  const UserProfileCard({
    Key? key,
    required this.user,
    this.onEdit,
  }) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return Card(
      margin: EdgeInsets.all(8),
      child: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 用户头像和基本信息
            Row(
              children: [
                CircleAvatar(
                  radius: 30,
                  backgroundImage: NetworkImage(user.avatarUrl),
                ),
                SizedBox(width: 16),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        user.name,
                        style: Theme.of(context).textTheme.headlineSmall,
                      ),
                      Text(
                        user.email,
                        style: Theme.of(context).textTheme.bodyMedium,
                      ),
                    ],
                  ),
                ),
                if (onEdit != null)
                  IconButton(
                    icon: Icon(Icons.edit),
                    onPressed: onEdit,
                  ),
              ],
            ),
            SizedBox(height: 12),
            // 用户描述
            if (user.bio.isNotEmpty)
              Text(
                user.bio,
                style: Theme.of(context).textTheme.bodySmall,
              ),
          ],
        ),
      ),
    );
  }
}

// User模型类
class User {
  final String name;
  final String email;
  final String avatarUrl;
  final String bio;
  
  const User({
    required this.name,
    required this.email,
    required this.avatarUrl,
    this.bio = '',
  });
}

3.2.2 StatefulWidget完整生命周期

// StatefulWidget完整生命周期演示
class LifecycleDemo extends StatefulWidget {
  final String title;
  
  const LifecycleDemo({Key? key, required this.title}) : super(key: key);
  
  @override
  _LifecycleDemoState createState() {
    print('📱 1. createState() - 创建State对象');
    return _LifecycleDemoState();
  }
}

class _LifecycleDemoState extends State<LifecycleDemo>
    with WidgetsBindingObserver {
  int _counter = 0;
  late String _title;
  
  // 2. 构造函数
  _LifecycleDemoState() {
    print('🏗️ 2. State构造函数');
  }
  
  // 3. initState - 只调用一次
  @override
  void initState() {
    super.initState();
    print('🎬 3. initState() - 初始化状态');
    _title = widget.title;
    
    // 添加生命周期观察者
    WidgetsBinding.instance.addObserver(this);
    
    // 异步初始化
    _asyncInit();
  }
  
  Future<void> _asyncInit() async {
    // 模拟异步数据加载
    await Future.delayed(Duration(seconds: 1));
    if (mounted) {  // 检查Widget是否还存在
      setState(() {
        _counter = 10;
      });
    }
  }
  
  // 4. didChangeDependencies - 依赖变化时调用
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print('🔄 4. didChangeDependencies() - 依赖改变');
  }
  
  // 5. build - 构建UI
  @override
  Widget build(BuildContext context) {
    print('🎨 5. build() - 构建UI, counter: $_counter');
    
    return Scaffold(
      appBar: AppBar(
        title: Text(_title),
        actions: [
          IconButton(
            icon: Icon(Icons.refresh),
            onPressed: _refresh,
          ),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '生命周期演示',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            SizedBox(height: 20),
            Text(
              '计数器:$_counter',
              style: Theme.of(context).textTheme.headlineSmall,
            ),
            SizedBox(height: 20),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                  onPressed: _increment,
                  child: Text('增加'),
                ),
                ElevatedButton(
                  onPressed: _decrement,
                  child: Text('减少'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
  
  // 6. didUpdateWidget - Widget配置改变时调用
  @override
  void didUpdateWidget(LifecycleDemo oldWidget) {
    super.didUpdateWidget(oldWidget);
    print('🔃 6. didUpdateWidget() - Widget更新');
    
    if (oldWidget.title != widget.title) {
      setState(() {
        _title = widget.title;
      });
    }
  }
  
  // 7. setState - 状态改变时调用
  void _increment() {
    setState(() {
      print('📈 setState() - 增加计数器');
      _counter++;
    });
  }
  
  void _decrement() {
    setState(() {
      print('📉 setState() - 减少计数器');
      _counter--;
    });
  }
  
  void _refresh() {
    setState(() {
      print('🔄 setState() - 刷新状态');
      _counter = 0;
    });
  }
  
  // 8. deactivate - Widget被移除时调用
  @override
  void deactivate() {
    print('⏸️ 8. deactivate() - Widget被停用');
    super.deactivate();
  }
  
  // 9. dispose - 最终清理
  @override
  void dispose() {
    print('🗑️ 9. dispose() - 清理资源');
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }
  
  // 应用生命周期监听
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    print('📱 应用状态改变:$state');
    
    switch (state) {
      case AppLifecycleState.resumed:
        print('📱 应用回到前台');
        break;
      case AppLifecycleState.inactive:
        print('📱 应用失去焦点');
        break;
      case AppLifecycleState.paused:
        print('📱 应用暂停');
        break;
      case AppLifecycleState.detached:
        print('📱 应用分离');
        break;
    }
  }
}

3.2.3 State管理最佳实践

// 复杂State管理示例
class ComplexStateWidget extends StatefulWidget {
  @override
  _ComplexStateWidgetState createState() => _ComplexStateWidgetState();
}

class _ComplexStateWidgetState extends State<ComplexStateWidget> {
  // 状态分组管理
  late UserController _userController;
  late AnimationController _animationController;
  late ScrollController _scrollController;
  
  // UI状态
  bool _isLoading = false;
  String? _errorMessage;
  List<User> _users = [];
  
  @override
  void initState() {
    super.initState();
    
    // 初始化控制器
    _userController = UserController();
    _animationController = AnimationController(
      duration: Duration(milliseconds: 300),
      vsync: this,
    );
    _scrollController = ScrollController();
    
    // 加载初始数据
    _loadUsers();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('复杂状态管理')),
      body: _buildBody(),
      floatingActionButton: _buildFAB(),
    );
  }
  
  Widget _buildBody() {
    if (_isLoading) {
      return Center(child: CircularProgressIndicator());
    }
    
    if (_errorMessage != null) {
      return Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.error, size: 64, color: Colors.red),
            SizedBox(height: 16),
            Text(_errorMessage!),
            ElevatedButton(
              onPressed: _loadUsers,
              child: Text('重试'),
            ),
          ],
        ),
      );
    }
    
    return RefreshIndicator(
      onRefresh: _loadUsers,
      child: ListView.builder(
        controller: _scrollController,
        itemCount: _users.length,
        itemBuilder: (context, index) {
          return UserListItem(
            user: _users[index],
            onTap: () => _showUserDetails(_users[index]),
            onDelete: () => _deleteUser(_users[index]),
          );
        },
      ),
    );
  }
  
  Widget _buildFAB() {
    return AnimatedBuilder(
      animation: _animationController,
      builder: (context, child) {
        return Transform.scale(
          scale: 1.0 + (_animationController.value * 0.1),
          child: FloatingActionButton(
            onPressed: _addUser,
            child: Icon(Icons.add),
          ),
        );
      },
    );
  }
  
  // 状态更新方法
  Future<void> _loadUsers() async {
    if (!mounted) return;
    
    setState(() {
      _isLoading = true;
      _errorMessage = null;
    });
    
    try {
      final users = await _userController.fetchUsers();
      if (mounted) {
        setState(() {
          _users = users;
          _isLoading = false;
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _errorMessage = '加载用户失败:$e';
          _isLoading = false;
        });
      }
    }
  }
  
  void _addUser() {
    _animationController.forward().then((_) {
      _animationController.reverse();
    });
    
    // 显示添加用户对话框
    _showAddUserDialog();
  }
  
  void _deleteUser(User user) async {
    final confirmed = await _showConfirmDialog('确定删除用户 ${user.name}?');
    if (confirmed) {
      setState(() {
        _users.remove(user);
      });
    }
  }
  
  void _showUserDetails(User user) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => UserDetailPage(user: user),
      ),
    );
  }
  
  void _showAddUserDialog() {
    showDialog(
      context: context,
      builder: (context) => AddUserDialog(
        onUserAdded: (user) {
          setState(() {
            _users.add(user);
          });
        },
      ),
    );
  }
  
  Future<bool> _showConfirmDialog(String message) async {
    return await showDialog<bool>(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('确认'),
        content: Text(message),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context, false),
            child: Text('取消'),
          ),
          TextButton(
            onPressed: () => Navigator.pop(context, true),
            child: Text('确定'),
          ),
        ],
      ),
    ) ?? false;
  }
  
  @override
  void dispose() {
    _userController.dispose();
    _animationController.dispose();
    _scrollController.dispose();
    super.dispose();
  }
}

// 用户控制器
class UserController {
  Future<List<User>> fetchUsers() async {
    // 模拟网络请求
    await Future.delayed(Duration(seconds: 2));
    return [
      User(
        name: '张三',
        email: 'zhangsan@example.com',
        avatarUrl: 'https://via.placeholder.com/100',
        bio: 'Flutter开发者',
      ),
      User(
        name: '李四',
        email: 'lisi@example.com',
        avatarUrl: 'https://via.placeholder.com/100',
        bio: 'UI设计师',
      ),
    ];
  }
  
  void dispose() {
    // 清理资源
  }
}

// 用户列表项组件
class UserListItem extends StatelessWidget {
  final User user;
  final VoidCallback onTap;
  final VoidCallback onDelete;
  
  const UserListItem({
    Key? key,
    required this.user,
    required this.onTap,
    required this.onDelete,
  }) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return Dismissible(
      key: Key(user.email),
      direction: DismissDirection.endToStart,
      onDismissed: (direction) => onDelete(),
      background: Container(
        color: Colors.red,
        alignment: Alignment.centerRight,
        padding: EdgeInsets.only(right: 16),
        child: Icon(Icons.delete, color: Colors.white),
      ),
      child: ListTile(
        leading: CircleAvatar(
          backgroundImage: NetworkImage(user.avatarUrl),
        ),
        title: Text(user.name),
        subtitle: Text(user.email),
        onTap: onTap,
      ),
    );
  }
}

3.3 布局Widget详解

3.3.1 Row和Column深入理解

// Row和Column的完整使用示例
class RowColumnDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Row和Column详解')),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Row布局演示
            _buildSectionTitle('Row布局演示'),
            _buildRowExamples(),
            
            SizedBox(height: 32),
            
            // Column布局演示
            _buildSectionTitle('Column布局演示'),
            _buildColumnExamples(),
            
            SizedBox(height: 32),
            
            // 嵌套布局演示
            _buildSectionTitle('嵌套布局演示'),
            _buildNestedExample(),
          ],
        ),
      ),
    );
  }
  
  Widget _buildSectionTitle(String title) {
    return Container(
      width: double.infinity,
      padding: EdgeInsets.symmetric(vertical: 8),
      child: Text(
        title,
        style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
      ),
    );
  }
  
  Widget _buildRowExamples() {
    return Column(
      children: [
        // 基本Row布局
        _buildExample(
          '基本Row布局',
          Row(
            children: [
              Container(width: 50, height: 50, color: Colors.red),
              Container(width: 50, height: 50, color: Colors.green),
              Container(width: 50, height: 50, color: Colors.blue),
            ],
          ),
        ),
        
        // MainAxisAlignment演示
        _buildExample(
          'MainAxisAlignment.spaceEvenly',
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              _buildColorBox(Colors.red, '1'),
              _buildColorBox(Colors.green, '2'),
              _buildColorBox(Colors.blue, '3'),
            ],
          ),
        ),
        
        _buildExample(
          'MainAxisAlignment.spaceBetween',
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              _buildColorBox(Colors.red, '1'),
              _buildColorBox(Colors.green, '2'),
              _buildColorBox(Colors.blue, '3'),
            ],
          ),
        ),
        
        // CrossAxisAlignment演示
        _buildExample(
          'CrossAxisAlignment.start',
          Container(
            height: 100,
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                _buildColorBox(Colors.red, '1', height: 40),
                _buildColorBox(Colors.green, '2', height: 60),
                _buildColorBox(Colors.blue, '3', height: 80),
              ],
            ),
          ),
        ),
        
        // Expanded使用
        _buildExample(
          'Expanded使用',
          Row(
            children: [
              _buildColorBox(Colors.red, '固定'),
              Expanded(
                flex: 2,
                child: _buildColorBox(Colors.green, 'Flex:2'),
              ),
              Expanded(
                flex: 1,
                child: _buildColorBox(Colors.blue, 'Flex:1'),
              ),
            ],
          ),
        ),
        
        // Flexible使用
        _buildExample(
          'Flexible使用',
          Row(
            children: [
              Flexible(
                child: Container(
                  height: 50,
                  color: Colors.red,
                  child: Center(
                    child: Text('这是一段很长的文本,演示Flexible的效果'),
                  ),
                ),
              ),
              Container(width: 100, height: 50, color: Colors.green),
            ],
          ),
        ),
      ],
    );
  }
  
  Widget _buildColumnExamples() {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // 第一列
        Expanded(
          child: Column(
            children: [
              _buildExample(
                'MainAxisAlignment.start',
                Container(
                  height: 150,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    children: [
                      _buildColorBox(Colors.red, '1'),
                      _buildColorBox(Colors.green, '2'),
                    ],
                  ),
                ),
              ),
              
              _buildExample(
                'MainAxisAlignment.center',
                Container(
                  height: 150,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      _buildColorBox(Colors.red, '1'),
                      _buildColorBox(Colors.green, '2'),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
        
        SizedBox(width: 16),
        
        // 第二列
        Expanded(
          child: Column(
            children: [
              _buildExample(
                'CrossAxisAlignment.stretch',
                Container(
                  height: 150,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      _buildColorBox(Colors.red, '拉伸'),
                      _buildColorBox(Colors.green, '拉伸'),
                    ],
                  ),
                ),
              ),
              
              _buildExample(
                'MainAxisSize.min',
                Container(
                  height: 150,
                  color: Colors.grey[200],
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      _buildColorBox(Colors.red, 'Min'),
                      _buildColorBox(Colors.green, 'Size'),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
  
  Widget _buildNestedExample() {
    return Container(
      padding: EdgeInsets.all(16),
      decoration: BoxDecoration(
        border: Border.all(color: Colors.grey),
        borderRadius: BorderRadius.circular(8),
      ),
      child: Column(
        children: [
          Text('复杂嵌套布局示例', style: TextStyle(fontWeight: FontWeight.bold)),
          SizedBox(height: 16),
          
          // 模拟社交媒体卡片布局
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // 用户头像
              CircleAvatar(
                radius: 25,
                backgroundColor: Colors.blue,
                child: Text('U', style: TextStyle(color: Colors.white)),
              ),
              
              SizedBox(width: 12),
              
              // 内容区域
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    // 用户信息行
                    Row(
                      children: [
                        Expanded(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                '用户名',
                                style: TextStyle(fontWeight: FontWeight.bold),
                              ),
                              Text(
                                '2小时前',
                                style: TextStyle(
                                  color: Colors.grey,
                                  fontSize: 12,
                                ),
                              ),
                            ],
                          ),
                        ),
                        Icon(Icons.more_vert, color: Colors.grey),
                      ],
                    ),
                    
                    SizedBox(height: 8),
                    
                    // 内容文本
                    Text('这是一条社交媒体动态的内容示例...'),
                    
                    SizedBox(height: 12),
                    
                    // 操作按钮行
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: [
                        _buildActionButton(Icons.thumb_up, '点赞'),
                        _buildActionButton(Icons.comment, '评论'),
                        _buildActionButton(Icons.share, '分享'),
                      ],
                    ),
                  ],
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
  
  Widget _buildActionButton(IconData icon, String label) {
    return Expanded(
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(icon, size: 16, color: Colors.grey),
          SizedBox(width: 4),
          Text(label, style: TextStyle(color: Colors.grey, fontSize: 12)),
        ],
      ),
    );
  }
  
  Widget _buildExample(String title, Widget child) {
    return Container(
      width: double.infinity,
      margin: EdgeInsets.only(bottom: 16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(title, style: TextStyle(fontSize: 14, color: Colors.grey[600])),
          SizedBox(height: 8),
          Container(
            width: double.infinity,
            decoration: BoxDecoration(
              border: Border.all(color: Colors.grey[300]!),
              borderRadius: BorderRadius.circular(4),
            ),
            child: child,
          ),
        ],
      ),
    );
  }
  
  Widget _buildColorBox(Color color, String text, {double? height}) {
    return Container(
      width: 60,
      height: height ?? 50,
      color: color,
      child: Center(
        child: Text(
          text,
          style: TextStyle(
            color: Colors.white,
            fontWeight: FontWeight.bold,
            fontSize: 12,
          ),
        ),
      ),
    );
  }
}

3.3.2 Stack和Positioned高级用法

// Stack和Positioned完整演示
class StackPositionedDemo extends StatefulWidget {
  @override
  _StackPositionedDemoState createState() => _StackPositionedDemoState();
}

class _StackPositionedDemoState extends State<StackPositionedDemo>
    with TickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _animation;
  
  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      duration: Duration(seconds: 2),
      vsync: this,
    );
    _animation = Tween<double>(begin: 0.0, end: 1.0).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
    );
    _animationController.repeat(reverse: true);
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Stack和Positioned详解')),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(16),
        child: Column(
          children: [
            _buildBasicStackExample(),
            SizedBox(height: 32),
            _buildPositionedExample(),
            SizedBox(height: 32),
            _buildAnimatedStackExample(),
            SizedBox(height: 32),
            _buildComplexLayoutExample(),
          ],
        ),
      ),
    );
  }
  
  Widget _buildBasicStackExample() {
    return _buildExampleCard(
      '基本Stack布局',
      Container(
        height: 200,
        child: Stack(
          children: [
            // 背景容器
            Container(
              width: double.infinity,
              height: double.infinity,
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [Colors.blue[300]!, Colors.blue[600]!],
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                ),
                borderRadius: BorderRadius.circular(12),
              ),
            ),
            
            // 左上角元素
            Positioned(
              top: 16,
              left: 16,
              child: Container(
                padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(20),
                ),
                child: Text('左上角', style: TextStyle(fontSize: 12)),
              ),
            ),
            
            // 右上角元素
            Positioned(
              top: 16,
              right: 16,
              child: Icon(Icons.favorite, color: Colors.white),
            ),
            
            // 居中元素
            Center(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Icon(Icons.star, size: 48, color: Colors.white),
                  Text(
                    '居中内容',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
            ),
            
            // 右下角元素
            Positioned(
              bottom: 16,
              right: 16,
              child: FloatingActionButton(
                mini: true,
                onPressed: () {},
                child: Icon(Icons.add),
              ),
            ),
          ],
        ),
      ),
    );
  }
  
  Widget _buildPositionedExample() {
    return _buildExampleCard(
      'Positioned详细用法',
      Container(
        height: 250,
        child: Stack(
          children: [
            // 背景网格
            CustomPaint(
              size: Size(double.infinity, double.infinity),
              painter: GridPainter(),
            ),
            
            // Positioned.fill - 填满整个Stack
            Positioned.fill(
              child: Container(
                margin: EdgeInsets.all(8),
                decoration: BoxDecoration(
                  color: Colors.blue.withOpacity(0.1),
                  border: Border.all(color: Colors.blue, width: 2),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Center(
                  child: Text(
                    'Positioned.fill',
                    style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
                  ),
                ),
              ),
            ),
            
            // Positioned.fromRect - 使用矩形定位
            Positioned.fromRect(
              rect: Rect.fromLTWH(50, 50, 100, 60),
              child: Container(
                decoration: BoxDecoration(
                  color: Colors.green,
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Center(
                  child: Text(
                    'fromRect',
                    style: TextStyle(color: Colors.white, fontSize: 12),
                  ),
                ),
              ),
            ),
            
            // Positioned.directional - 支持RTL
            Positioned.directional(
              textDirection: TextDirection.ltr,
              start: 16,
              bottom: 16,
              child: Container(
                padding: EdgeInsets.all(8),
                decoration: BoxDecoration(
                  color: Colors.orange,
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Text(
                  'Directional',
                  style: TextStyle(color: Colors.white, fontSize: 12),
                ),
              ),
            ),
            
            // 相对定位
            Positioned(
              top: 100,
              right: 20,
              width: 80,
              height: 40,
              child: Container(
                decoration: BoxDecoration(
                  color: Colors.purple,
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Center(
                  child: Text(
                    '固定尺寸',
                    style: TextStyle(color: Colors.white, fontSize: 10),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
  
  Widget _buildAnimatedStackExample() {
    return _buildExampleCard(
      '动画Stack效果',
      Container(
        height: 200,
        child: AnimatedBuilder(
          animation: _animation,
          builder: (context, child) {
            return Stack(
              children: [
                // 背景
                Container(
                  width: double.infinity,
                  height: double.infinity,
                  decoration: BoxDecoration(
                    color: Colors.grey[100],
                    borderRadius: BorderRadius.circular(12),
                  ),
                ),
                
                // 动画圆圈1
                AnimatedPositioned(
                  duration: Duration(milliseconds: 100),
                  left: 20 + (_animation.value * 200),
                  top: 20,
                  child: Container(
                    width: 40,
                    height: 40,
                    decoration: BoxDecoration(
                      color: Colors.red,
                      shape: BoxShape.circle,
                    ),
                  ),
                ),
                
                // 动画圆圈2
                AnimatedPositioned(
                  duration: Duration(milliseconds: 100),
                  right: 20 + (_animation.value * 200),
                  top: 80,
                  child: Container(
                    width: 40,
                    height: 40,
                    decoration: BoxDecoration(
                      color: Colors.green,
                      shape: BoxShape.circle,
                    ),
                  ),
                ),
                
                // 动画圆圈3
                AnimatedPositioned(
                  duration: Duration(milliseconds: 100),
                  left: 20 + (_animation.value * 200),
                  bottom: 20,
                  child: Container(
                    width: 40,
                    height: 40,
                    decoration: BoxDecoration(
                      color: Colors.blue,
                      shape: BoxShape.circle,
                    ),
                  ),
                ),
                
                // 中心文本
                Center(
                  child: Text(
                    '动画演示',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                      color: Colors.grey[700],
                    ),
                  ),
                ),
              ],
            );
          },
        ),
      ),
    );
  }
  
  Widget _buildComplexLayoutExample() {
    return _buildExampleCard(
      '复杂Stack布局 - 卡片叠加效果',
      Container(
        height: 300,
        child: Stack(
          children: [
            // 卡片1 - 最底层
            Positioned(
              top: 40,
              left: 30,
              right: 30,
              bottom: 80,
              child: Transform.rotate(
                angle: -0.05,
                child: _buildCard(Colors.red, '卡片 1'),
              ),
            ),
            
            // 卡片2 - 中层
            Positioned(
              top: 30,
              left: 20,
              right: 20,
              bottom: 60,
              child: Transform.rotate(
                angle: 0.02,
                child: _buildCard(Colors.green, '卡片 2'),
              ),
            ),
            
            // 卡片3 - 顶层
            Positioned(
              top: 20,
              left: 10,
              right: 10,
              bottom: 40,
              child: _buildCard(Colors.blue, '卡片 3'),
            ),
            
            // 装饰元素
            Positioned(
              top: 0,
              right: 0,
              child: Container(
                width: 60,
                height: 60,
                decoration: BoxDecoration(
                  color: Colors.orange,
                  shape: BoxShape.circle,
                ),
                child: Icon(Icons.star, color: Colors.white),
              ),
            ),
            
            // 底部操作栏
            Positioned(
              bottom: 0,
              left: 0,
              right: 0,
              child: Container(
                height: 50,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.only(
                    bottomLeft: Radius.circular(12),
                    bottomRight: Radius.circular(12),
                  ),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black12,
                      blurRadius: 4,
                      offset: Offset(0, -2),
                    ),
                  ],
                ),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    IconButton(
                      icon: Icon(Icons.shuffle),
                      onPressed: () {},
                    ),
                    IconButton(
                      icon: Icon(Icons.favorite_border),
                      onPressed: () {},
                    ),
                    IconButton(
                      icon: Icon(Icons.share),
                      onPressed: () {},
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
  
  Widget _buildCard(Color color, String title) {
    return Container(
      decoration: BoxDecoration(
        color: color,
        borderRadius: BorderRadius.circular(12),
        boxShadow: [
          BoxShadow(
            color: Colors.black26,
            blurRadius: 8,
            offset: Offset(0, 4),
          ),
        ],
      ),
      child: Center(
        child: Text(
          title,
          style: TextStyle(
            color: Colors.white,
            fontSize: 24,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    );
  }
  
  Widget _buildExampleCard(String title, Widget child) {
    return Card(
      elevation: 4,
      child: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              title,
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
                color: Colors.grey[700],
              ),
            ),
            SizedBox(height: 16),
            child,
          ],
        ),
      ),
    );
  }
  
  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }
}

// 网格绘制器
class GridPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.grey[300]!
      ..strokeWidth = 1;
    
    // 绘制垂直线
    for (double x = 0; x <= size.width; x += 20) {
      canvas.drawLine(Offset(x, 0), Offset(x, size.height), paint);
    }
    
    // 绘制水平线
    for (double y = 0; y <= size.height; y += 20) {
      canvas.drawLine(Offset(0, y), Offset(size.width, y), paint);
    }
  }
  
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

3.4 容器Widget深入理解

3.4.1 Container全面解析

// Container完整功能演示
class ContainerDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Container详解')),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _buildSectionTitle('基础Container'),
            _buildBasicContainerExamples(),
            
            SizedBox(height: 24),
            _buildSectionTitle('装饰效果'),
            _buildDecorationExamples(),
            
            SizedBox(height: 24),
            _buildSectionTitle('变换效果'),
            _buildTransformExamples(),
            
            SizedBox(height: 24),
            _buildSectionTitle('实际应用案例'),
            _buildPracticalExamples(),
          ],
        ),
      ),
    );
  }
  
  Widget _buildSectionTitle(String title) {
    return Padding(
      padding: EdgeInsets.symmetric(vertical: 8),
      child: Text(
        title,
        style: TextStyle(
          fontSize: 20,
          fontWeight: FontWeight.bold,
          color: Colors.blue[700],
        ),
      ),
    );
  }
  
  Widget _buildBasicContainerExamples() {
    return Column(
      children: [
        // 基础Container
        _buildExample(
          '基础Container - 尺寸和颜色',
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Container(
                width: 80,
                height: 80,
                color: Colors.red,
                child: Center(child: Text('固定尺寸', style: TextStyle(color: Colors.white))),
              ),
              Container(
                padding: EdgeInsets.all(16),
                color: Colors.green,
                child: Text('内边距', style: TextStyle(color: Colors.white)),
              ),
              Container(
                margin: EdgeInsets.all(8),
                padding: EdgeInsets.all(8),
                color: Colors.blue,
                child: Text('边距+内边距', style: TextStyle(color: Colors.white, fontSize: 10)),
              ),
            ],
          ),
        ),
        
        // 对齐方式
        _buildExample(
          'Container对齐 - Alignment',
          Row(
            children: [
              Expanded(
                child: Container(
                  height: 100,
                  color: Colors.grey[200],
                  alignment: Alignment.topLeft,
                  child: Container(
                    width: 40,
                    height: 40,
                    color: Colors.red,
                    child: Center(child: Text('TL', style: TextStyle(color: Colors.white, fontSize: 10))),
                  ),
                ),
              ),
              SizedBox(width: 8),
              Expanded(
                child: Container(
                  height: 100,
                  color: Colors.grey[200],
                  alignment: Alignment.center,
                  child: Container(
                    width: 40,
                    height: 40,
                    color: Colors.green,
                    child: Center(child: Text('C', style: TextStyle(color: Colors.white))),
                  ),
                ),
              ),
              SizedBox(width: 8),
              Expanded(
                child: Container(
                  height: 100,
                  color: Colors.grey[200],
                  alignment: Alignment.bottomRight,
                  child: Container(
                    width: 40,
                    height: 40,
                    color: Colors.blue,
                    child: Center(child: Text('BR', style: TextStyle(color: Colors.white, fontSize: 10))),
                  ),
                ),
              ),
            ],
          ),
        ),
        
        // 约束演示
        _buildExample(
          'Container约束 - Constraints',
          Column(
            children: [
              Container(
                constraints: BoxConstraints(
                  minWidth: 150,
                  minHeight: 50,
                  maxWidth: 200,
                  maxHeight: 80,
                ),
                color: Colors.orange,
                child: Text('约束容器\n宽度: 150-200\n高度: 50-80'),
              ),
              SizedBox(height: 8),
              Container(
                constraints: BoxConstraints.expand(height: 60),
                color: Colors.purple,
                child: Center(
                  child: Text('扩展宽度,固定高度', style: TextStyle(color: Colors.white)),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
  
  Widget _buildDecorationExamples() {
    return Column(
      children: [
        // 基础装饰
        _buildExample(
          'BoxDecoration - 边框和圆角',
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Container(
                width: 80,
                height: 80,
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Center(child: Text('圆角', style: TextStyle(color: Colors.white))),
              ),
              Container(
                width: 80,
                height: 80,
                decoration: BoxDecoration(
                  color: Colors.white,
                  border: Border.all(color: Colors.red, width: 3),
                  borderRadius: BorderRadius.circular(40),
                ),
                child: Center(child: Text('圆形边框', style: TextStyle(color: Colors.red))),
              ),
              Container(
                width: 80,
                height: 80,
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                    colors: [Colors.purple, Colors.pink],
                    begin: Alignment.topLeft,
                    end: Alignment.bottomRight,
                  ),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Center(child: Text('渐变', style: TextStyle(color: Colors.white))),
              ),
            ],
          ),
        ),
        
        // 阴影效果
        _buildExample(
          'BoxShadow - 阴影效果',
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Container(
                width: 80,
                height: 80,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(8),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.grey.withOpacity(0.5),
                      spreadRadius: 2,
                      blurRadius: 5,
                      offset: Offset(0, 3),
                    ),
                  ],
                ),
                child: Center(child: Text('基础阴影')),
              ),
              Container(
                width: 80,
                height: 80,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(8),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.blue.withOpacity(0.3),
                      spreadRadius: 0,
                      blurRadius: 10,
                      offset: Offset(0, 0),
                    ),
                  ],
                ),
                child: Center(child: Text('发光效果')),
              ),
              Container(
                width: 80,
                height: 80,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(8),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black.withOpacity(0.1),
                      spreadRadius: 1,
                      blurRadius: 3,
                      offset: Offset(0, 1),
                    ),
                    BoxShadow(
                      color: Colors.black.withOpacity(0.2),
                      spreadRadius: 0,
                      blurRadius: 6,
                      offset: Offset(0, 3),
                    ),
                  ],
                ),
                child: Center(child: Text('多重阴影')),
              ),
            ],
          ),
        ),
        
        // 复杂装饰
        _buildExample(
          '复杂装饰组合',
          Container(
            height: 120,
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [
                  Colors.deepPurple[400]!,
                  Colors.deepPurple[600]!,
                  Colors.deepPurple[800]!,
                ],
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
              ),
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(20),
                topRight: Radius.circular(20),
                bottomLeft: Radius.circular(8),
                bottomRight: Radius.circular(8),
              ),
              border: Border.all(
                color: Colors.white.withOpacity(0.3),
                width: 2,
              ),
              boxShadow: [
                BoxShadow(
                  color: Colors.deepPurple.withOpacity(0.3),
                  spreadRadius: 2,
                  blurRadius: 8,
                  offset: Offset(0, 4),
                ),
              ],
            ),
            child: Stack(
              children: [
                // 背景图案
                Positioned.fill(
                  child: CustomPaint(
                    painter: PatternPainter(),
                  ),
                ),
                // 内容
                Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(Icons.star, size: 32, color: Colors.white),
                      SizedBox(height: 8),
                      Text(
                        '复杂装饰效果',
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 16,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
  
  Widget _buildTransformExamples() {
    return Column(
      children: [
        _buildExample(
          'Transform变换效果',
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Container(
                width: 80,
                height: 80,
                transform: Matrix4.rotationZ(0.2),
                decoration: BoxDecoration(
                  color: Colors.red,
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Center(child: Text('旋转', style: TextStyle(color: Colors.white))),
              ),
              Container(
                width: 80,
                height: 80,
                transform: Matrix4.skewX(0.2),
                decoration: BoxDecoration(
                  color: Colors.green,
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Center(child: Text('倾斜', style: TextStyle(color: Colors.white))),
              ),
              Container(
                width: 80,
                height: 80,
                transform: Matrix4.identity()..scale(0.8),
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Center(child: Text('缩放', style: TextStyle(color: Colors.white))),
              ),
            ],
          ),
        ),
      ],
    );
  }
  
  Widget _buildPracticalExamples() {
    return Column(
      children: [
        // 卡片样式
        _buildExample(
          '实用卡片样式',
          Container(
            width: double.infinity,
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(12),
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withOpacity(0.1),
                  spreadRadius: 1,
                  blurRadius: 4,
                  offset: Offset(0, 2),
                ),
              ],
            ),
            child: Column(
              children: [
                // 头部区域
                Container(
                  width: double.infinity,
                  padding: EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    gradient: LinearGradient(
                      colors: [Colors.blue[400]!, Colors.blue[600]!],
                    ),
                    borderRadius: BorderRadius.only(
                      topLeft: Radius.circular(12),
                      topRight: Radius.circular(12),
                    ),
                  ),
                  child: Row(
                    children: [
                      Icon(Icons.credit_card, color: Colors.white),
                      SizedBox(width: 12),
                      Expanded(
                        child: Text(
                          '信用卡',
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 18,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ),
                      Text(
                        '**** 1234',
                        style: TextStyle(color: Colors.white),
                      ),
                    ],
                  ),
                ),
                // 内容区域
                Padding(
                  padding: EdgeInsets.all(16),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text('余额', style: TextStyle(color: Colors.grey[600])),
                              Text(
                                '¥12,345.67',
                                style: TextStyle(
                                  fontSize: 24,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ],
                          ),
                          Container(
                            padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
                            decoration: BoxDecoration(
                              color: Colors.green[100],
                              borderRadius: BorderRadius.circular(20),
                            ),
                            child: Text(
                              '正常',
                              style: TextStyle(
                                color: Colors.green[700],
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                          ),
                        ],
                      ),
                      SizedBox(height: 16),
                      Row(
                        children: [
                          Expanded(
                            child: Container(
                              padding: EdgeInsets.symmetric(vertical: 12),
                              decoration: BoxDecoration(
                                border: Border.all(color: Colors.grey[300]!),
                                borderRadius: BorderRadius.circular(8),
                              ),
                              child: Center(child: Text('转账')),
                            ),
                          ),
                          SizedBox(width: 12),
                          Expanded(
                            child: Container(
                              padding: EdgeInsets.symmetric(vertical: 12),
                              decoration: BoxDecoration(
                                color: Colors.blue,
                                borderRadius: BorderRadius.circular(8),
                              ),
                              child: Center(
                                child: Text(
                                  '充值',
                                  style: TextStyle(color: Colors.white),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
  
  Widget _buildExample(String title, Widget child) {
    return Container(
      width: double.infinity,
      margin: EdgeInsets.only(bottom: 16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            title,
            style: TextStyle(
              fontSize: 14,
              fontWeight: FontWeight.w500,
              color: Colors.grey[700],
            ),
          ),
          SizedBox(height: 8),
          child,
        ],
      ),
    );
  }
}

// 图案绘制器
class PatternPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.white.withOpacity(0.1)
      ..style = PaintingStyle.stroke
      ..strokeWidth = 1;
    
    // 绘制菱形图案
    for (double x = 0; x < size.width; x += 20) {
      for (double y = 0; y < size.height; y += 20) {
        final path = Path();
        path.moveTo(x + 10, y);
        path.lineTo(x + 20, y + 10);
        path.lineTo(x + 10, y + 20);
        path.lineTo(x, y + 10);
        path.close();
        canvas.drawPath(path, paint);
      }
    }
  }
  
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

3.5 滚动Widget详解

3.5.1 ListView完整实现

// ListView完整功能演示
class ListViewDemo extends StatefulWidget {
  @override
  _ListViewDemoState createState() => _ListViewDemoState();
}

class _ListViewDemoState extends State<ListViewDemo> {
  final ScrollController _scrollController = ScrollController();
  final List<String> _items = List.generate(50, (index) => '项目 ${index + 1}');
  bool _showScrollButton = false;
  
  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_scrollListener);
  }
  
  void _scrollListener() {
    if (_scrollController.offset > 200 && !_showScrollButton) {
      setState(() => _showScrollButton = true);
    } else if (_scrollController.offset <= 200 && _showScrollButton) {
      setState(() => _showScrollButton = false);
    }
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('ListView详解')),
      body: Column(
        children: [
          // 控制面板
          Container(
            padding: EdgeInsets.all(16),
            color: Colors.grey[100],
            child: Row(
              children: [
                ElevatedButton(
                  onPressed: _scrollToTop,
                  child: Text('回到顶部'),
                ),
                SizedBox(width: 8),
                ElevatedButton(
                  onPressed: _scrollToBottom,
                  child: Text('滚动到底部'),
                ),
                SizedBox(width: 8),
                ElevatedButton(
                  onPressed: _addItem,
                  child: Text('添加项目'),
                ),
              ],
            ),
          ),
          
          // ListView区域
          Expanded(
            child: Stack(
              children: [
                _buildListView(),
                
                // 滚动到顶部按钮
                if (_showScrollButton)
                  Positioned(
                    right: 16,
                    bottom: 16,
                    child: FloatingActionButton(
                      mini: true,
                      onPressed: _scrollToTop,
                      child: Icon(Icons.keyboard_arrow_up),
                    ),
                  ),
              ],
            ),
          ),
        ],
      ),
    );
  }
  
  Widget _buildListView() {
    return ListView.builder(
      controller: _scrollController,
      // 性能优化参数
      itemExtent: 80, // 固定项目高度以提升性能
      cacheExtent: 500, // 缓存区域大小
      
      itemCount: _items.length + 2, // +2 用于头部和尾部
      itemBuilder: (context, index) {
        // 头部项目
        if (index == 0) {
          return _buildHeader();
        }
        
        // 尾部项目
        if (index == _items.length + 1) {
          return _buildFooter();
        }
        
        // 普通项目
        final itemIndex = index - 1;
        return _buildListItem(itemIndex);
      },
    );
  }
  
  Widget _buildHeader() {
    return Container(
      height: 80,
      decoration: BoxDecoration(
        gradient: LinearGradient(
          colors: [Colors.blue[400]!, Colors.blue[600]!],
        ),
      ),
      child: Center(
        child: Text(
          'ListView 演示头部',
          style: TextStyle(
            color: Colors.white,
            fontSize: 20,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    );
  }
  
  Widget _buildFooter() {
    return Container(
      height: 80,
      color: Colors.grey[200],
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.done_all, color: Colors.grey[600]),
            SizedBox(height: 4),
            Text(
              '已加载 ${_items.length} 个项目',
              style: TextStyle(color: Colors.grey[600]),
            ),
          ],
        ),
      ),
    );
  }
  
  Widget _buildListItem(int index) {
    return Dismissible(
      key: Key(_items[index]),
      direction: DismissDirection.endToStart,
      onDismissed: (direction) {
        final item = _items[index];
        setState(() {
          _items.removeAt(index);
        });
        
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('$item 已删除'),
            action: SnackBarAction(
              label: '撤销',
              onPressed: () {
                setState(() {
                  _items.insert(index, item);
                });
              },
            ),
          ),
        );
      },
      background: Container(
        color: Colors.red,
        alignment: Alignment.centerRight,
        padding: EdgeInsets.only(right: 16),
        child: Icon(Icons.delete, color: Colors.white),
      ),
      child: Container(
        height: 80,
        child: Card(
          margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
          child: ListTile(
            leading: CircleAvatar(
              backgroundColor: _getColorForIndex(index),
              child: Text('${index + 1}'),
            ),
            title: Text(_items[index]),
            subtitle: Text('这是第 ${index + 1} 个项目的描述'),
            trailing: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                IconButton(
                  icon: Icon(Icons.edit),
                  onPressed: () => _editItem(index),
                ),
                Icon(Icons.drag_handle, color: Colors.grey),
              ],
            ),
            onTap: () => _showItemDetails(index),
          ),
        ),
      ),
    );
  }
  
  Color _getColorForIndex(int index) {
    final colors = [
      Colors.red,
      Colors.green,
      Colors.blue,
      Colors.orange,
      Colors.purple,
    ];
    return colors[index % colors.length];
  }
  
  void _scrollToTop() {
    _scrollController.animateTo(
      0,
      duration: Duration(milliseconds: 500),
      curve: Curves.easeInOut,
    );
  }
  
  void _scrollToBottom() {
    _scrollController.animateTo(
      _scrollController.position.maxScrollExtent,
      duration: Duration(milliseconds: 500),
      curve: Curves.easeInOut,
    );
  }
  
  void _addItem() {
    setState(() {
      _items.add('新项目 ${_items.length + 1}');
    });
    
    // 滚动到新添加的项目
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _scrollController.animateTo(
        _scrollController.position.maxScrollExtent,
        duration: Duration(milliseconds: 300),
        curve: Curves.easeOut,
      );
    });
  }
  
  void _editItem(int index) {
    showDialog(
      context: context,
      builder: (context) {
        String newValue = _items[index];
        return AlertDialog(
          title: Text('编辑项目'),
          content: TextField(
            controller: TextEditingController(text: newValue),
            onChanged: (value) => newValue = value,
            decoration: InputDecoration(
              labelText: '项目名称',
              border: OutlineInputBorder(),
            ),
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(context),
              child: Text('取消'),
            ),
            TextButton(
              onPressed: () {
                setState(() {
                  _items[index] = newValue;
                });
                Navigator.pop(context);
              },
              child: Text('保存'),
            ),
          ],
        );
      },
    );
  }
  
  void _showItemDetails(int index) {
    showModalBottomSheet(
      context: context,
      builder: (context) {
        return Container(
          height: 300,
          padding: EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                '项目详情',
                style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
              ),
              SizedBox(height: 16),
              Text('名称: ${_items[index]}'),
              Text('索引: $index'),
              Text('位置: 第 ${index + 1} 个'),
              SizedBox(height: 16),
              Text('操作:'),
              SizedBox(height: 8),
              Row(
                children: [
                  ElevatedButton(
                    onPressed: () {
                      Navigator.pop(context);
                      _editItem(index);
                    },
                    child: Text('编辑'),
                  ),
                  SizedBox(width: 8),
                  ElevatedButton(
                    onPressed: () {
                      Navigator.pop(context);
                      setState(() {
                        _items.removeAt(index);
                      });
                    },
                    style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
                    child: Text('删除'),
                  ),
                ],
              ),
            ],
          ),
        );
      },
    );
  }
  
  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }
}

3.5.2 GridView和CustomScrollView

// GridView和CustomScrollView演示
class GridViewCustomScrollDemo extends StatefulWidget {
  @override
  _GridViewCustomScrollDemoState createState() => _GridViewCustomScrollDemoState();
}

class _GridViewCustomScrollDemoState extends State<GridViewCustomScrollDemo>
    with TickerProviderStateMixin {
  late TabController _tabController;
  final ScrollController _scrollController = ScrollController();
  
  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 3, vsync: this);
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('GridView & CustomScrollView'),
        bottom: TabBar(
          controller: _tabController,
          tabs: [
            Tab(text: 'GridView'),
            Tab(text: 'CustomScrollView'),
            Tab(text: '复杂滚动'),
          ],
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: [
          _buildGridViewDemo(),
          _buildCustomScrollViewDemo(),
          _buildComplexScrollDemo(),
        ],
      ),
    );
  }
  
  Widget _buildGridViewDemo() {
    return Column(
      children: [
        // 控制面板
        Container(
          padding: EdgeInsets.all(16),
          color: Colors.grey[100],
          child: Text(
            'GridView演示 - 网格布局',
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
        ),
        
        Expanded(
          child: GridView.builder(
            padding: EdgeInsets.all(16),
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2, // 每行2个
              crossAxisSpacing: 16, // 水平间距
              mainAxisSpacing: 16, // 垂直间距
              childAspectRatio: 0.8, // 宽高比
            ),
            itemCount: 20,
            itemBuilder: (context, index) {
              return _buildGridItem(index);
            },
          ),
        ),
      ],
    );
  }
  
  Widget _buildGridItem(int index) {
    final colors = [
      Colors.red,
      Colors.green,
      Colors.blue,
      Colors.orange,
      Colors.purple,
      Colors.teal,
    ];
    
    return Container(
      decoration: BoxDecoration(
        color: colors[index % colors.length],
        borderRadius: BorderRadius.circular(12),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withOpacity(0.1),
            blurRadius: 4,
            offset: Offset(0, 2),
          ),
        ],
      ),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(
            _getIconForIndex(index),
            size: 48,
            color: Colors.white,
          ),
          SizedBox(height: 8),
          Text(
            '项目 ${index + 1}',
            style: TextStyle(
              color: Colors.white,
              fontWeight: FontWeight.bold,
              fontSize: 16,
            ),
          ),
          SizedBox(height: 4),
          Text(
            '详细描述',
            style: TextStyle(
              color: Colors.white70,
              fontSize: 12,
            ),
          ),
        ],
      ),
    );
  }
  
  IconData _getIconForIndex(int index) {
    final icons = [
      Icons.home,
      Icons.star,
      Icons.favorite,
      Icons.settings,
      Icons.person,
      Icons.camera,
    ];
    return icons[index % icons.length];
  }
  
  Widget _buildCustomScrollViewDemo() {
    return CustomScrollView(
      slivers: [
        // SliverAppBar
        SliverAppBar(
          expandedHeight: 200,
          floating: false,
          pinned: true,
          flexibleSpace: FlexibleSpaceBar(
            title: Text('可折叠标题'),
            background: Container(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [Colors.blue[400]!, Colors.blue[600]!],
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                ),
              ),
              child: Center(
                child: Icon(Icons.landscape, size: 80, color: Colors.white),
              ),
            ),
          ),
        ),
        
        // SliverPersistentHeader
        SliverPersistentHeader(
          pinned: true,
          delegate: CustomSliverDelegate(
            minHeight: 60,
            maxHeight: 60,
            child: Container(
              color: Colors.grey[200],
              child: Center(
                child: Text(
                  '固定头部',
                  style: TextStyle(fontWeight: FontWeight.bold),
                ),
              ),
            ),
          ),
        ),
        
        // SliverList
        SliverList(
          delegate: SliverChildBuilderDelegate(
            (context, index) {
              return Container(
                height: 80,
                margin: EdgeInsets.symmetric(horizontal: 16, vertical: 4),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(8),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black.withOpacity(0.1),
                      blurRadius: 2,
                      offset: Offset(0, 1),
                    ),
                  ],
                ),
                child: ListTile(
                  leading: CircleAvatar(
                    backgroundColor: Colors.blue,
                    child: Text('${index + 1}'),
                  ),
                  title: Text('列表项目 ${index + 1}'),
                  subtitle: Text('这是第 ${index + 1} 个项目'),
                  trailing: Icon(Icons.arrow_forward_ios),
                ),
              );
            },
            childCount: 10,
          ),
        ),
        
        // SliverGrid
        SliverPadding(
          padding: EdgeInsets.all(16),
          sliver: SliverGrid(
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 3,
              crossAxisSpacing: 8,
              mainAxisSpacing: 8,
            ),
            delegate: SliverChildBuilderDelegate(
              (context, index) {
                return Container(
                  decoration: BoxDecoration(
                    color: Colors.orange[300],
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: Center(
                    child: Text(
                      '${index + 1}',
                      style: TextStyle(
                        color: Colors.white,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                );
              },
              childCount: 12,
            ),
          ),
        ),
        
        // SliverToBoxAdapter
        SliverToBoxAdapter(
          child: Container(
            height: 100,
            margin: EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Colors.green[100],
              borderRadius: BorderRadius.circular(12),
            ),
            child: Center(
              child: Text(
                '单个Widget适配器',
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }
  
  Widget _buildComplexScrollDemo() {
    return NestedScrollView(
      headerSliverBuilder: (context, innerBoxIsScrolled) {
        return [
          SliverAppBar(
            title: Text('嵌套滚动'),
            floating: true,
            snap: true,
            forceElevated: innerBoxIsScrolled,
          ),
        ];
      },
      body: TabBarView(
        children: [
          // 第一个标签页
          ListView.builder(
            itemCount: 30,
            itemBuilder: (context, index) {
              return ListTile(
                title: Text('嵌套列表项目 ${index + 1}'),
                leading: Icon(Icons.list),
              );
            },
          ),
          // 第二个标签页  
          GridView.builder(
            padding: EdgeInsets.all(8),
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2,
              crossAxisSpacing: 8,
              mainAxisSpacing: 8,
            ),
            itemCount: 20,
            itemBuilder: (context, index) {
              return Container(
                decoration: BoxDecoration(
                  color: Colors.blue[100],
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Center(child: Text('网格 ${index + 1}')),
              );
            },
          ),
        ],
      ),
    );
  }
  
  @override
  void dispose() {
    _tabController.dispose();
    _scrollController.dispose();
    super.dispose();
  }
}

// 自定义Sliver委托
class CustomSliverDelegate extends SliverPersistentHeaderDelegate {
  final double minHeight;
  final double maxHeight;
  final Widget child;
  
  CustomSliverDelegate({
    required this.minHeight,
    required this.maxHeight,
    required this.child,
  });
  
  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return SizedBox.expand(child: child);
  }
  
  @override
  double get maxExtent => maxHeight;
  
  @override
  double get minExtent => minHeight;
  
  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxExtent ||
           minHeight != oldDelegate.minExtent;
  }
}


网站公告

今日签到

点亮在社区的每一天
去签到