Flutter之Widget体系与布局原理

第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;
  }
}
相关推荐
安东尼肉店6 小时前
Android compose屏幕适配终极解决方案
android
2501_916007476 小时前
HTTPS 抓包乱码怎么办?原因剖析、排查步骤与实战工具对策(HTTPS 抓包乱码、gzipbrotli、TLS 解密、iOS 抓包)
android·ios·小程序·https·uni-app·iphone·webview
feiyangqingyun7 小时前
基于Qt和FFmpeg的安卓监控模拟器/手机摄像头模拟成onvif和28181设备
android·qt·ffmpeg
用户20187928316711 小时前
ANR之RenderThread不可中断睡眠state=D
android
煤球王子11 小时前
简单学:Android14中的Bluetooth—PBAP下载
android
小趴菜822711 小时前
安卓接入Max广告源
android
齊家治國平天下11 小时前
Android 14 系统 ANR (Application Not Responding) 深度分析与解决指南
android·anr
ZHANG13HAO11 小时前
Android 13.0 Framework 实现应用通知使用权默认开启的技术指南
android
【ql君】qlexcel11 小时前
Android 安卓RIL介绍
android·安卓·ril
写点啥呢12 小时前
android12解决非CarProperty接口深色模式设置后开机无法保持
android·车机·aosp·深色模式·座舱