Skip to content
On this page

Flutter Widget系统

Flutter的Widget系统是其核心架构,一切UI元素都是Widget。理解Widget系统对于掌握Flutter开发至关重要。本章将详细介绍Widget系统的核心概念、类型和使用方法。

Widget系统基础

Widget、Element和RenderObject的关系

在Flutter中,有三个核心概念:Widget、Element和RenderObject,它们共同构成了Flutter的UI系统。

dart
// Widget示例 - 描述UI配置
class MyButton extends StatelessWidget {
  final String text;
  final VoidCallback onPressed;

  const MyButton({
    Key? key,
    required this.text,
    required this.onPressed,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onPressed,
      child: Container(
        padding: EdgeInsets.all(16.0),
        decoration: BoxDecoration(
          color: Colors.blue,
          borderRadius: BorderRadius.circular(8.0),
        ),
        child: Text(
          text,
          style: TextStyle(color: Colors.white),
        ),
      ),
    );
  }
}

// Widget的构建过程演示
class WidgetBuildDemo extends StatefulWidget {
  @override
  _WidgetBuildDemoState createState() => _WidgetBuildDemoState();
}

class _WidgetBuildDemoState extends State<WidgetBuildDemo> {
  int counter = 0;

  @override
  Widget build(BuildContext context) {
    print('build() called'); // 每次setState都会调用
    
    return Scaffold(
      appBar: AppBar(title: Text('Widget Build Demo')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Counter: $counter'),
            SizedBox(height: 20),
            MyButton(
              text: 'Increment',
              onPressed: () {
                setState(() {
                  counter++;
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

Widget分类

StatelessWidget

StatelessWidget用于不需要状态变化的UI组件。

dart
class WelcomeCard extends StatelessWidget {
  final String title;
  final String subtitle;
  final IconData icon;

  const WelcomeCard({
    Key? key,
    required this.title,
    required this.subtitle,
    required this.icon,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 4.0,
      margin: EdgeInsets.all(16.0),
      child: Padding(
        padding: EdgeInsets.all(16.0),
        child: Row(
          children: [
            Icon(icon, size: 48, color: Colors.blue),
            SizedBox(width: 16),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    title,
                    style: Theme.of(context).textTheme.headlineSmall,
                  ),
                  SizedBox(height: 8),
                  Text(
                    subtitle,
                    style: Theme.of(context).textTheme.bodyMedium,
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class StatelessExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Stateless Widget Example')),
      body: Column(
        children: [
          WelcomeCard(
            title: 'Welcome',
            subtitle: 'This is a stateless widget example',
            icon: Icons.home,
          ),
          WelcomeCard(
            title: 'About',
            subtitle: 'Stateless widgets never change',
            icon: Icons.info,
          ),
        ],
      ),
    );
  }
}

StatefulWidget

StatefulWidget用于需要状态变化的UI组件。

dart
class CounterWidget extends StatefulWidget {
  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Stateful Widget Example')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'Counter Value:',
              style: Theme.of(context).textTheme.titleLarge,
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.displayLarge?.copyWith(
                    color: Colors.blue,
                  ),
            ),
          ],
        ),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: _incrementCounter,
            child: Icon(Icons.add),
            heroTag: 'increment',
          ),
          SizedBox(width: 8),
          FloatingActionButton(
            onPressed: _decrementCounter,
            child: Icon(Icons.remove),
            heroTag: 'decrement',
          ),
        ],
      ),
    );
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  void _decrementCounter() {
    setState(() {
      if (_counter > 0) _counter--;
    });
  }
}

基础Widget

Container

Container是最常用的布局Widget,提供装饰、填充、边距等功能。

dart
class ContainerDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Container Demo')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          children: [
            // 基础Container
            Container(
              width: 200,
              height: 100,
              color: Colors.blue,
              child: Center(
                child: Text(
                  'Basic Container',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
            SizedBox(height: 16),
            
            // 带装饰的Container
            Container(
              width: 250,
              height: 120,
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [Colors.purple, Colors.orange],
                ),
                borderRadius: BorderRadius.circular(20),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black26,
                    blurRadius: 10,
                    offset: Offset(0, 5),
                  ),
                ],
              ),
              child: Center(
                child: Text(
                  'Styled Container',
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
            SizedBox(height: 16),
            
            // 带边距和填充的Container
            Container(
              margin: EdgeInsets.all(8.0),
              padding: EdgeInsets.all(16.0),
              decoration: BoxDecoration(
                color: Colors.green,
                borderRadius: BorderRadius.circular(12),
              ),
              child: Text(
                'Container with padding and margin',
                style: TextStyle(color: Colors.white),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Text Widget

Text Widget用于显示文本内容。

dart
class TextDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Text Widget Demo')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Basic Text',
              style: TextStyle(fontSize: 16),
            ),
            SizedBox(height: 16),
            
            // 样式化文本
            Text(
              'Styled Text with various properties',
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
                color: Colors.blue,
                fontStyle: FontStyle.italic,
                decoration: TextDecoration.underline,
              ),
            ),
            SizedBox(height: 16),
            
            // 富文本
            RichText(
              text: TextSpan(
                style: TextStyle(color: Colors.black, fontSize: 16),
                children: [
                  TextSpan(text: 'This is '),
                  TextSpan(
                    text: 'bold',
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                  TextSpan(text: ' and this is '),
                  TextSpan(
                    text: 'italic',
                    style: TextStyle(fontStyle: FontStyle.italic),
                  ),
                  TextSpan(text: '.'),
                ],
              ),
            ),
            SizedBox(height: 16),
            
            // 长文本处理
            Text(
              'This is a very long text that demonstrates how Flutter handles text overflow. '
              'When text is too long to fit in its container, Flutter provides various ways '
              'to handle the overflow, such as clipping, fading, or showing ellipsis.',
              maxLines: 2,
              overflow: TextOverflow.ellipsis,
              style: TextStyle(fontSize: 14),
            ),
          ],
        ),
      ),
    );
  }
}

Image Widget

Image Widget用于显示图像。

dart
class ImageDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Image Widget Demo')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: SingleChildScrollView(
          child: Column(
            children: [
              // 网络图片
              Container(
                height: 200,
                width: double.infinity,
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(12),
                  child: Image.network(
                    'https://via.placeholder.com/400x200',
                    fit: BoxFit.cover,
                    loadingBuilder: (context, child, loadingProgress) {
                      if (loadingProgress == null) return child;
                      return Center(
                        child: CircularProgressIndicator(
                          value: loadingProgress.expectedTotalBytes != null
                              ? loadingProgress.cumulativeBytesLoaded /
                                  loadingProgress.expectedTotalBytes!
                              : null,
                        ),
                      );
                    },
                    errorBuilder: (context, error, stackTrace) {
                      return Icon(
                        Icons.error,
                        size: 50,
                        color: Colors.red,
                      );
                    },
                  ),
                ),
              ),
              SizedBox(height: 16),
              
              // 本地图片
              Image.asset(
                'assets/images/sample.jpg', // 需要在pubspec.yaml中声明
                width: 200,
                height: 150,
                fit: BoxFit.cover,
              ),
              SizedBox(height: 16),
              
              // 图片修饰
              Container(
                width: 200,
                height: 200,
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  image: DecorationImage(
                    image: NetworkImage('https://via.placeholder.com/200'),
                    fit: BoxFit.cover,
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

布局Widget

Row和Column

Row用于水平布局,Column用于垂直布局。

dart
class RowColumnDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Row & Column Demo')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          children: [
            // Row示例
            Container(
              height: 80,
              color: Colors.grey[100],
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Container(
                    width: 60,
                    height: 60,
                    color: Colors.red,
                    child: Center(child: Text('1', style: TextStyle(color: Colors.white))),
                  ),
                  Container(
                    width: 60,
                    height: 60,
                    color: Colors.green,
                    child: Center(child: Text('2', style: TextStyle(color: Colors.white))),
                  ),
                  Container(
                    width: 60,
                    height: 60,
                    color: Colors.blue,
                    child: Center(child: Text('3', style: TextStyle(color: Colors.white))),
                  ),
                ],
              ),
            ),
            SizedBox(height: 16),
            
            // Column示例
            Container(
              width: double.infinity,
              color: Colors.grey[100],
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Container(
                    width: double.infinity,
                    height: 50,
                    color: Colors.orange,
                    child: Center(child: Text('Top')),
                  ),
                  Container(
                    width: double.infinity,
                    height: 50,
                    color: Colors.pink,
                    child: Center(child: Text('Middle')),
                  ),
                  Container(
                    width: double.infinity,
                    height: 50,
                    color: Colors.purple,
                    child: Center(child: Text('Bottom')),
                  ),
                ],
              ),
            ),
            SizedBox(height: 16),
            
            // Expanded示例
            Container(
              height: 60,
              child: Row(
                children: [
                  Container(
                    width: 60,
                    color: Colors.grey,
                    child: Center(child: Text('Fixed')),
                  ),
                  Expanded(
                    child: Container(
                      color: Colors.lightBlue,
                      child: Center(child: Text('Expanded')),
                    ),
                  ),
                  Container(
                    width: 60,
                    color: Colors.grey,
                    child: Center(child: Text('Fixed')),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Flexible和Expanded

Flexible和Expanded用于处理可用空间的分配。

dart
class FlexibleExpandedDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Flexible & Expanded Demo')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          children: [
            // Flexible示例
            Container(
              height: 60,
              child: Row(
                children: [
                  Flexible(
                    flex: 2,
                    child: Container(
                      color: Colors.red,
                      child: Center(child: Text('Flex 2', style: TextStyle(color: Colors.white))),
                    ),
                  ),
                  Flexible(
                    flex: 1,
                    child: Container(
                      color: Colors.green,
                      child: Center(child: Text('Flex 1', style: TextStyle(color: Colors.white))),
                    ),
                  ),
                  Flexible(
                    flex: 1,
                    child: Container(
                      color: Colors.blue,
                      child: Center(child: Text('Flex 1', style: TextStyle(color: Colors.white))),
                    ),
                  ),
                ],
              ),
            ),
            SizedBox(height: 16),
            
            // Expanded示例
            Container(
              height: 60,
              child: Row(
                children: [
                  Container(
                    width: 50,
                    color: Colors.grey,
                    child: Center(child: Text('50')),
                  ),
                  Expanded(
                    child: Container(
                      color: Colors.yellow,
                      child: Center(child: Text('Expanded')),
                    ),
                  ),
                  Container(
                    width: 50,
                    color: Colors.grey,
                    child: Center(child: Text('50')),
                  ),
                ],
              ),
            ),
            SizedBox(height: 16),
            
            // Nested example
            Container(
              height: 100,
              child: Row(
                children: [
                  Expanded(
                    flex: 1,
                    child: Container(
                      color: Colors.purple,
                      child: Column(
                        children: [
                          Expanded(
                            child: Container(color: Colors.purple[200], child: Center(child: Text('Nested 1'))),
                          ),
                          Expanded(
                            child: Container(color: Colors.purple[400], child: Center(child: Text('Nested 2'))),
                          ),
                        ],
                      ),
                    ),
                  ),
                  Expanded(
                    flex: 2,
                    child: Container(
                      color: Colors.orange,
                      child: Center(child: Text('Main Expanded')),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

ListView

ListView用于显示可滚动的列表。

dart
class ListViewDemo extends StatelessWidget {
  final List<String> items = List.generate(50, (index) => 'Item ${index + 1}');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('ListView Demo')),
      body: ListView.builder(
        itemCount: items.length,
        itemBuilder: (context, index) {
          return Card(
            margin: EdgeInsets.symmetric(horizontal: 16, vertical: 4),
            child: ListTile(
              leading: CircleAvatar(child: Text('${index + 1}')),
              title: Text(items[index]),
              subtitle: Text('Description for ${items[index]}'),
              trailing: Icon(Icons.arrow_forward_ios),
              onTap: () {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Tapped ${items[index]}')),
                );
              },
            ),
          );
        },
      ),
    );
  }
}

// 水平ListView
class HorizontalListView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 120,
      child: ListView.separated(
        scrollDirection: Axis.horizontal,
        itemCount: 20,
        separatorBuilder: (context, index) => SizedBox(width: 8),
        itemBuilder: (context, index) {
          return Container(
            width: 100,
            decoration: BoxDecoration(
              color: Colors.blue[100],
              borderRadius: BorderRadius.circular(8),
            ),
            child: Center(child: Text('Item $index')),
          );
        },
      ),
    );
  }
}

GridView

GridView用于显示网格布局。

dart
class GridViewDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GridView Demo')),
      body: GridView.builder(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 2, // 每行2个项目
          crossAxisSpacing: 8,
          mainAxisSpacing: 8,
          childAspectRatio: 1.2, // 高宽比
        ),
        itemCount: 20,
        itemBuilder: (context, index) {
          return Card(
            child: GridTile(
              header: Container(
                color: Colors.blue,
                child: Center(
                  child: Text(
                    'Header $index',
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
              child: Center(child: Text('Item $index')),
              footer: Container(
                color: Colors.grey,
                child: Center(
                  child: Text(
                    'Footer',
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

// 网格视图的其他样式
class GridViewVariants extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          title: Text('GridView Variants'),
          bottom: TabBar(
            tabs: [
              Tab(text: 'Fixed Count'),
              Tab(text: 'Max Cross Size'),
              Tab(text: 'Builder'),
            ],
          ),
        ),
        body: TabBarView(
          children: [
            // Fixed cross axis count
            GridView.count(
              crossAxisCount: 3,
              children: List.generate(12, (index) {
                return Card(
                  child: Center(child: Text('Item $index')),
                );
              }),
            ),
            
            // Max cross axis extent
            GridView.extent(
              maxCrossAxisExtent: 150,
              childAspectRatio: 1,
              children: List.generate(15, (index) {
                return Card(
                  color: Colors.primaries[index % Colors.primaries.length],
                  child: Center(child: Text('Item $index')),
                );
              }),
            ),
            
            // Builder
            GridView.builder(
              gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                maxCrossAxisExtent: 200,
                mainAxisSpacing: 10,
                crossAxisSpacing: 10,
                childAspectRatio: 1,
              ),
              itemCount: 25,
              itemBuilder: (context, index) {
                return Card(
                  child: Center(child: Text('Item $index')),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

手势检测Widget

GestureDetector

GestureDetector用于检测各种手勢。

dart
class GestureDemo extends StatefulWidget {
  @override
  _GestureDemoState createState() => _GestureDemoState();
}

class _GestureDemoState extends State<GestureDemo> {
  String _gestureInfo = 'Tap, double tap, or long press the box below';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Gesture Detection Demo')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 200,
              height: 200,
              child: GestureDetector(
                onTap: () {
                  setState(() {
                    _gestureInfo = 'Single tap detected!';
                  });
                },
                onDoubleTap: () {
                  setState(() {
                    _gestureInfo = 'Double tap detected!';
                  });
                },
                onLongPress: () {
                  setState(() {
                    _gestureInfo = 'Long press detected!';
                  });
                },
                onPanUpdate: (details) {
                  // 拖拽移动
                  setState(() {
                    _gestureInfo = 'Dragging...';
                  });
                },
                onScaleUpdate: (details) {
                  // 缩放
                  setState(() {
                    _gestureInfo = 'Scaling...';
                  });
                },
                child: Container(
                  decoration: BoxDecoration(
                    color: Colors.blue,
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: Center(
                    child: Text(
                      'Gesture Area',
                      style: TextStyle(color: Colors.white),
                    ),
                  ),
                ),
              ),
            ),
            SizedBox(height: 32),
            Text(
              _gestureInfo,
              style: TextStyle(fontSize: 16),
              textAlign: TextAlign.center,
            ),
          ],
        ),
      ),
    );
  }
}

表单Widget

TextField

TextField用于文本输入。

dart
class FormDemo extends StatefulWidget {
  @override
  _FormDemoState createState() => _FormDemoState();
}

class _FormDemoState extends State<FormDemo> {
  final _formKey = GlobalKey<FormState>();
  final _nameController = TextEditingController();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  
  String _formData = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Form Demo')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: ListView(
            children: [
              TextFormField(
                controller: _nameController,
                decoration: InputDecoration(
                  labelText: 'Name',
                  hintText: 'Enter your name',
                  prefixIcon: Icon(Icons.person),
                  border: OutlineInputBorder(),
                ),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter your name';
                  }
                  if (value.length < 2) {
                    return 'Name should be at least 2 characters';
                  }
                  return null;
                },
              ),
              SizedBox(height: 16),
              
              TextFormField(
                controller: _emailController,
                decoration: InputDecoration(
                  labelText: 'Email',
                  hintText: 'Enter your email',
                  prefixIcon: Icon(Icons.email),
                  border: OutlineInputBorder(),
                ),
                keyboardType: TextInputType.emailAddress,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter your email';
                  }
                  if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) {
                    return 'Please enter a valid email';
                  }
                  return null;
                },
              ),
              SizedBox(height: 16),
              
              TextFormField(
                controller: _passwordController,
                decoration: InputDecoration(
                  labelText: 'Password',
                  hintText: 'Enter your password',
                  prefixIcon: Icon(Icons.lock),
                  border: OutlineInputBorder(),
                ),
                obscureText: true,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter your password';
                  }
                  if (value.length < 6) {
                    return 'Password should be at least 6 characters';
                  }
                  return null;
                },
              ),
              SizedBox(height: 24),
              
              ElevatedButton(
                onPressed: _submitForm,
                style: ElevatedButton.styleFrom(
                  padding: EdgeInsets.symmetric(vertical: 16),
                ),
                child: Text('Submit', style: TextStyle(fontSize: 16)),
              ),
              
              SizedBox(height: 24),
              
              Text(
                _formData,
                style: TextStyle(fontSize: 16),
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _submitForm() {
    if (_formKey.currentState!.validate()) {
      setState(() {
        _formData = 'Name: ${_nameController.text}\n'
                    'Email: ${_emailController.text}\n'
                    'Password: ${_passwordController.text}';
      });
      
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Form submitted successfully!')),
      );
    }
  }

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

自定义Widget

组合现有Widget

dart
// 自定义输入框Widget
class CustomInputField extends StatelessWidget {
  final String label;
  final String hint;
  final IconData icon;
  final TextEditingController controller;
  final String? Function(String?)? validator;
  final bool obscureText;

  const CustomInputField({
    Key? key,
    required this.label,
    required this.hint,
    required this.icon,
    required this.controller,
    this.validator,
    this.obscureText = false,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      controller: controller,
      decoration: InputDecoration(
        labelText: label,
        hintText: hint,
        prefixIcon: Icon(icon),
        border: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
        ),
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: BorderSide(color: Colors.blue, width: 2),
        ),
      ),
      obscureText: obscureText,
      validator: validator,
    );
  }
}

// 自定义按钮Widget
class CustomButton extends StatelessWidget {
  final String text;
  final VoidCallback onPressed;
  final Color color;
  final double height;

  const CustomButton({
    Key? key,
    required this.text,
    required this.onPressed,
    this.color = Colors.blue,
    this.height = 50,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: height,
      width: double.infinity,
      child: ElevatedButton(
        onPressed: onPressed,
        style: ElevatedButton.styleFrom(
          backgroundColor: color,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(12),
          ),
        ),
        child: Text(
          text,
          style: TextStyle(
            fontSize: 16,
            fontWeight: FontWeight.bold,
            color: Colors.white,
          ),
        ),
      ),
    );
  }
}

// 使用自定义Widget的表单
class CustomFormDemo extends StatefulWidget {
  @override
  _CustomFormDemoState createState() => _CustomFormDemoState();
}

class _CustomFormDemoState extends State<CustomFormDemo> {
  final _formKey = GlobalKey<FormState>();
  final _nameController = TextEditingController();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Custom Widget Form')),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              CustomInputField(
                label: 'Full Name',
                hint: 'Enter your full name',
                icon: Icons.person,
                controller: _nameController,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Name is required';
                  }
                  return null;
                },
              ),
              SizedBox(height: 16),
              
              CustomInputField(
                label: 'Email',
                hint: 'Enter your email',
                icon: Icons.email,
                controller: _emailController,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Email is required';
                  }
                  if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) {
                    return 'Invalid email format';
                  }
                  return null;
                },
              ),
              SizedBox(height: 16),
              
              CustomInputField(
                label: 'Password',
                hint: 'Enter your password',
                icon: Icons.lock,
                controller: _passwordController,
                obscureText: true,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Password is required';
                  }
                  if (value.length < 6) {
                    return 'Password must be at least 6 characters';
                  }
                  return null;
                },
              ),
              SizedBox(height: 32),
              
              CustomButton(
                text: 'Sign Up',
                onPressed: () {
                  if (_formKey.currentState!.validate()) {
                    print('Form is valid');
                    // 处理表单提交
                  }
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

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

Widget生命周期

dart
class LifecycleDemo extends StatefulWidget {
  @override
  _LifecycleDemoState createState() => _LifecycleDemoState();
}

class _LifecycleDemoState extends State<LifecycleDemo> {
  int counter = 0;

  @override
  void initState() {
    super.initState();
    print('initState called');
    // 初始化工作
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print('didChangeDependencies called');
    // InheritedWidget变化时调用
  }

  @override
  void didUpdateWidget(covariant LifecycleDemo oldWidget) {
    super.didUpdateWidget(oldWidget);
    print('didUpdateWidget called');
    // 父Widget重建时调用
  }

  @override
  void deactivate() {
    super.deactivate();
    print('deactivate called');
    // Widget从树中移除时调用(可能重新插入)
  }

  @override
  void dispose() {
    print('dispose called');
    // 清理工作
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    print('build called');
    return Scaffold(
      appBar: AppBar(title: Text('Lifecycle Demo')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Counter: $counter'),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  counter++;
                });
              },
              child: Text('Increment'),
            ),
          ],
        ),
      ),
    );
  }
}

总结

Flutter的Widget系统提供了丰富的UI构建组件,通过组合不同的Widget可以创建复杂的用户界面。理解Widget的分类、生命周期和使用方法是Flutter开发的核心技能。合理使用StatelessWidget和StatefulWidget,结合布局Widget和交互Widget,可以构建出功能丰富、用户体验良好的应用程序。