在这里插入图片描述

2.1 Text Widget - 就像写字板

Text Widget就像现实中的各种文字载体:标语牌、书本、标签等。

🔍 Text Widget的内部实现原理

想象Text Widget就像一个智能的文字工厂,让我们看看它是如何从基础Widget一步步构建出来的:

// 🏗️ Text Widget的简化实现原理(教学版本)

// 第一层:最基础的Widget抽象类
abstract class Widget {
  // 每个Widget都有一个key来标识自己
  final Key? key;
  
  Widget({this.key});
  
  // 核心方法:创建Element
  Element createElement();
}

// 第二层:StatelessWidget基类
abstract class StatelessWidget extends Widget {
  StatelessWidget({Key? key}) : super(key: key);
  
  
  StatelessElement createElement() => StatelessElement(this);
  
  // 子类必须实现的方法
  Widget build(BuildContext context);
}

// 第三层:Text Widget的实际实现
class MyText extends StatelessWidget {
  final String data;           // 要显示的文字
  final TextStyle? style;      // 文字样式
  final TextAlign? textAlign;  // 文字对齐方式
  final int? maxLines;         // 最大行数
  final TextOverflow? overflow; // 溢出处理
  
  const MyText(
    this.data, {
    Key? key,
    this.style,
    this.textAlign,
    this.maxLines,
    this.overflow,
  }) : super(key: key);
  
  
  Widget build(BuildContext context) {
    // 🎨 这里是Text Widget的核心逻辑
    
    // 1. 获取主题中的默认文字样式
    final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);
    TextStyle? effectiveTextStyle = style;
    
    if (style == null || style!.inherit) {
      effectiveTextStyle = defaultTextStyle.style.merge(style);
    }
    
    // 2. 创建RichText Widget(Text的底层实现)
    return RichText(
      textAlign: textAlign ?? defaultTextStyle.textAlign ?? TextAlign.start,
      maxLines: maxLines ?? defaultTextStyle.maxLines,
      overflow: overflow ?? defaultTextStyle.overflow,
      text: TextSpan(
        text: data,
        style: effectiveTextStyle,
      ),
    );
  }
}

// 🎭 生活类比:Text Widget就像一个文字印刷厂

/*
想象Text Widget的工作流程:

1. 原材料输入(构造函数)
   - 文字内容 (data)
   - 样式要求 (style)
   - 排版要求 (textAlign, maxLines等)

2. 工厂处理(build方法)
   - 检查主题设置(就像印刷厂的标准模板)
   - 合并样式(就像选择字体、颜色、大小)
   - 创建最终产品(RichText)

3. 产品输出
   - 在屏幕上显示格式化的文字
*/

// 🔧 Text Widget的核心组件分析

// TextSpan - 文字片段(就像一个个文字积木)
class TextSpanExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return RichText(
      text: TextSpan(
        text: '这是普通文字,',
        style: TextStyle(color: Colors.black, fontSize: 16),
        children: [
          TextSpan(
            text: '这是粗体文字,',
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
          TextSpan(
            text: '这是彩色文字!',
            style: TextStyle(color: Colors.red),
          ),
        ],
      ),
    );
  }
}

// TextStyle - 文字样式(就像文字的化妆师)
class TextStyleExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(
          '样式演示',
          style: TextStyle(
            fontSize: 24,              // 字体大小(就像放大镜的倍数)
            fontWeight: FontWeight.bold, // 字体粗细(就像笔的粗细)
            color: Colors.blue,         // 颜色(就像墨水的颜色)
            letterSpacing: 2.0,        // 字母间距(就像字与字的距离)
            wordSpacing: 4.0,          // 单词间距
            height: 1.5,               // 行高(就像行与行的距离)
            decoration: TextDecoration.underline, // 装饰(下划线)
            decorationColor: Colors.red,          // 装饰颜色
            decorationStyle: TextDecorationStyle.wavy, // 装饰样式(波浪线)
            shadows: [                 // 阴影效果
              Shadow(
                offset: Offset(2.0, 2.0),
                blurRadius: 3.0,
                color: Colors.grey,
              ),
            ],
          ),
        ),
      ],
    );
  }
}

// 🎯 Text Widget的渲染流程

/*
Text Widget的渲染就像一个文字处理流水线:

1. 输入阶段:
   - 接收文字内容和样式参数
   - 就像印刷厂接收订单

2. 处理阶段:
   - 解析文字内容
   - 应用样式设置
   - 计算布局信息
   - 就像排版师设计版面

3. 渲染阶段:
   - 在Canvas上绘制文字
   - 应用颜色、阴影等效果
   - 就像印刷机印刷成品

4. 显示阶段:
   - 在屏幕上显示最终结果
   - 就像成品展示
*/

// 🧪 自定义Text Widget示例
class CustomText extends StatelessWidget {
  final String text;
  final Color? color;
  final double? fontSize;
  final bool isBold;
  
  const CustomText(
    this.text, {
    Key? key,
    this.color,
    this.fontSize,
    this.isBold = false,
  }) : super(key: key);
  
  
  Widget build(BuildContext context) {
    return Text(
      text,
      style: TextStyle(
        color: color ?? Colors.black,
        fontSize: fontSize ?? 16,
        fontWeight: isBold ? FontWeight.bold : FontWeight.normal,
      ),
    );
  }
}
class TextExamples extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('文字展示大全')),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 普通文字 - 就像普通的标签
            Text('这是普通文字'),
            
            SizedBox(height: 16),
            
            // 大标题 - 就像海报上的主标题
            Text(
              '这是大标题',
              style: TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
                color: Colors.blue,
              ),
            ),
            
            SizedBox(height: 16),
            
            // 彩色文字 - 就像用彩色笔写的字
            Text(
              '这是彩色文字',
              style: TextStyle(
                fontSize: 18,
                color: Colors.red,
                fontStyle: FontStyle.italic, // 斜体
              ),
            ),
            
            SizedBox(height: 16),
            
            // 多行文字 - 就像一段文章
            Text(
              '这是一段很长的文字,用来演示文字换行的效果。'
              '当文字太长时,会自动换到下一行显示。'
              '就像我们平时看书一样。',
              style: TextStyle(fontSize: 16),
            ),
            
            SizedBox(height: 16),
            
            // 限制行数的文字 - 就像报纸的标题栏
            Text(
              '这是一段超级超级超级长的文字,但是我们只显示一行,多余的用省略号表示',
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
              style: TextStyle(fontSize: 16),
            ),
          ],
        ),
      ),
    );
  }
}

2.2 Image Widget - 就像相框

Image Widget就像现实中的各种图片展示方式:相框、海报、屏幕等。

🔍 Image Widget的内部实现原理

想象Image Widget就像一个智能的图片处理工厂,让我们看看它是如何从基础Widget构建出来的:

// 🏗️ Image Widget的简化实现原理(教学版本)

// Image Widget的核心实现
class MyImage extends StatefulWidget {
  final ImageProvider image;    // 图片提供者(数据源)
  final double? width;         // 宽度
  final double? height;        // 高度
  final BoxFit? fit;          // 适应方式
  final Color? color;         // 颜色滤镜
  final BlendMode? colorBlendMode; // 混合模式
  
  const MyImage({
    Key? key,
    required this.image,
    this.width,
    this.height,
    this.fit,
    this.color,
    this.colorBlendMode,
  }) : super(key: key);
  
  
  _MyImageState createState() => _MyImageState();
}

class _MyImageState extends State<MyImage> {
  ImageStream? _imageStream;
  ImageInfo? _imageInfo;
  bool _isLoading = true;
  
  
  void initState() {
    super.initState();
    _loadImage();
  }
  
  void _loadImage() {
    // 🎯 图片加载流程
    
    // 1. 从ImageProvider获取ImageStream
    _imageStream = widget.image.resolve(ImageConfiguration.empty);
    
    // 2. 监听图片加载完成
    _imageStream!.addListener(ImageStreamListener(
      (ImageInfo info, bool synchronousCall) {
        setState(() {
          _imageInfo = info;
          _isLoading = false;
        });
      },
      onError: (dynamic error, StackTrace? stackTrace) {
        setState(() {
          _isLoading = false;
        });
      },
    ));
  }
  
  
  Widget build(BuildContext context) {
    if (_isLoading) {
      // 加载中显示占位符
      return Container(
        width: widget.width,
        height: widget.height,
        color: Colors.grey[300],
        child: Center(
          child: CircularProgressIndicator(),
        ),
      );
    }
    
    if (_imageInfo == null) {
      // 加载失败显示错误
      return Container(
        width: widget.width,
        height: widget.height,
        color: Colors.grey[300],
        child: Center(
          child: Icon(Icons.error),
        ),
      );
    }
    
    // 🎨 使用RawImage渲染图片(Image的底层实现)
    return RawImage(
      image: _imageInfo!.image,
      width: widget.width,
      height: widget.height,
      fit: widget.fit ?? BoxFit.scaleDown,
      color: widget.color,
      colorBlendMode: widget.colorBlendMode,
    );
  }
  
  
  void dispose() {
    _imageStream?.removeListener(ImageStreamListener((info, sync) {}));
    super.dispose();
  }
}

// 🎭 生活类比:Image Widget就像一个智能相框工厂

/*
想象Image Widget的工作流程:

1. 订单接收(构造函数)
   - 图片来源 (ImageProvider)
   - 尺寸要求 (width, height)
   - 显示方式 (fit)
   - 特效要求 (color, colorBlendMode)

2. 图片获取(resolve阶段)
   - 网络图片:从网络下载
   - 本地图片:从文件系统读取
   - 资源图片:从应用包中提取
   - 就像相框工厂从不同渠道获取照片

3. 图片处理(加载阶段)
   - 解码图片数据
   - 缓存处理
   - 尺寸调整
   - 就像照片冲洗和裁剪

4. 显示渲染(build阶段)
   - 应用适应方式
   - 添加颜色滤镜
   - 在屏幕上绘制
   - 就像把照片装进相框展示
*/

// 🔧 ImageProvider 系列 - 图片数据源

// 网络图片提供者
class NetworkImageExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Image(
      image: NetworkImage('https://picsum.photos/300/200'),
      // 等价于:Image.network('https://picsum.photos/300/200')
    );
  }
}

// 资源图片提供者
class AssetImageExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Image(
      image: AssetImage('assets/images/logo.png'),
      // 等价于:Image.asset('assets/images/logo.png')
    );
  }
}

// 文件图片提供者
class FileImageExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Image(
      image: FileImage(File('/path/to/image.jpg')),
      // 等价于:Image.file(File('/path/to/image.jpg'))
    );
  }
}

// 内存图片提供者
class MemoryImageExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    // 假设bytes是图片的字节数据
    Uint8List bytes = Uint8List(0);
    return Image(
      image: MemoryImage(bytes),
      // 等价于:Image.memory(bytes)
    );
  }
}

// 🎯 BoxFit 适应方式详解

class BoxFitExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('不同的BoxFit效果:'),
        SizedBox(height: 16),
        
        // 创建一个网格来展示不同的fit效果
        GridView.count(
          shrinkWrap: true,
          crossAxisCount: 2,
          children: [
            _buildFitExample(BoxFit.fill, 'fill - 填满容器'),
            _buildFitExample(BoxFit.contain, 'contain - 完整显示'),
            _buildFitExample(BoxFit.cover, 'cover - 覆盖容器'),
            _buildFitExample(BoxFit.fitWidth, 'fitWidth - 适应宽度'),
            _buildFitExample(BoxFit.fitHeight, 'fitHeight - 适应高度'),
            _buildFitExample(BoxFit.scaleDown, 'scaleDown - 缩小显示'),
          ],
        ),
      ],
    );
  }
  
  Widget _buildFitExample(BoxFit fit, String description) {
    return Column(
      children: [
        Container(
          width: 120,
          height: 80,
          decoration: BoxDecoration(
            border: Border.all(color: Colors.grey),
          ),
          child: Image.network(
            'https://picsum.photos/200/300', // 高宽比不同的图片
            fit: fit,
          ),
        ),
        SizedBox(height: 4),
        Text(description, style: TextStyle(fontSize: 10)),
      ],
    );
  }
}

// 🎨 图片处理和特效

class ImageEffectsExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('图片特效演示:'),
        SizedBox(height: 16),
        
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            // 原图
            Column(
              children: [
                Container(
                  width: 80,
                  height: 80,
                  child: Image.network('https://picsum.photos/100/100'),
                ),
                Text('原图'),
              ],
            ),
            
            // 颜色滤镜
            Column(
              children: [
                Container(
                  width: 80,
                  height: 80,
                  child: Image.network(
                    'https://picsum.photos/100/100',
                    color: Colors.red.withOpacity(0.5),
                    colorBlendMode: BlendMode.multiply,
                  ),
                ),
                Text('红色滤镜'),
              ],
            ),
            
            // 灰度效果
            Column(
              children: [
                Container(
                  width: 80,
                  height: 80,
                  child: ColorFiltered(
                    colorFilter: ColorFilter.mode(
                      Colors.grey,
                      BlendMode.saturation,
                    ),
                    child: Image.network('https://picsum.photos/100/100'),
                  ),
                ),
                Text('灰度效果'),
              ],
            ),
          ],
        ),
      ],
    );
  }
}

// 🔄 图片缓存机制

/*
Image Widget的缓存就像一个智能的照片管理系统:

1. 内存缓存(Memory Cache)
   - 就像桌面上的常用照片
   - 访问最快,但容量有限
   - 应用关闭后消失

2. 磁盘缓存(Disk Cache)
   - 就像相册里的照片
   - 访问较快,容量较大
   - 应用关闭后仍然存在

3. 缓存策略
   - LRU(最近最少使用)淘汰
   - 就像整理相册,把不常看的照片收起来

4. 缓存控制
   - 可以清除缓存
   - 可以预加载图片
   - 可以设置缓存大小
*/

// 自定义图片缓存示例
class CustomImageCache extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: () {
            // 清除图片缓存
            PaintingBinding.instance.imageCache.clear();
            print('图片缓存已清除');
          },
          child: Text('清除图片缓存'),
        ),
        
        ElevatedButton(
          onPressed: () {
            // 预加载图片
            precacheImage(
              NetworkImage('https://picsum.photos/400/300'),
              context,
            );
            print('图片预加载完成');
          },
          child: Text('预加载图片'),
        ),
        
        Text('当前缓存信息:'),
        Text('缓存图片数量: ${PaintingBinding.instance.imageCache.currentSize}'),
        Text('缓存大小限制: ${PaintingBinding.instance.imageCache.maximumSize}'),
      ],
    );
  }
}

// 🧪 自定义Image Widget示例
class CustomImageWidget extends StatelessWidget {
  final String imageUrl;
  final double? width;
  final double? height;
  final Widget? placeholder;
  final Widget? errorWidget;
  
  const CustomImageWidget({
    Key? key,
    required this.imageUrl,
    this.width,
    this.height,
    this.placeholder,
    this.errorWidget,
  }) : super(key: key);
  
  
  Widget build(BuildContext context) {
    return Container(
      width: width,
      height: height,
      child: Image.network(
        imageUrl,
        fit: BoxFit.cover,
        loadingBuilder: (context, child, loadingProgress) {
          if (loadingProgress == null) return child;
          
          return placeholder ?? Container(
            color: Colors.grey[300],
            child: Center(
              child: CircularProgressIndicator(
                value: loadingProgress.expectedTotalBytes != null
                    ? loadingProgress.cumulativeBytesLoaded / 
                      loadingProgress.expectedTotalBytes!
                    : null,
              ),
            ),
          );
        },
        errorBuilder: (context, error, stackTrace) {
          return errorWidget ?? Container(
            color: Colors.grey[300],
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(Icons.error, color: Colors.red),
                  Text('加载失败', style: TextStyle(color: Colors.red)),
                ],
              ),
            ),
          );
        },
      ),
    );
  }
}
class ImageExamples extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('图片展示大全')),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(16),
        child: Column(
          children: [
            // 网络图片 - 就像从互联网下载的照片
            Container(
              height: 200,
              width: double.infinity,
              child: Image.network(
                'https://picsum.photos/400/200',
                fit: BoxFit.cover, // 就像把照片裁剪适合相框
                loadingBuilder: (context, child, loadingProgress) {
                  if (loadingProgress == null) return child;
                  return Center(
                    child: CircularProgressIndicator(), // 加载中的转圈圈
                  );
                },
                errorBuilder: (context, error, stackTrace) {
                  return Container(
                    color: Colors.grey[300],
                    child: Center(
                      child: Text('图片加载失败'),
                    ),
                  );
                },
              ),
            ),
            
            SizedBox(height: 20),
            
            // 本地资源图片 - 就像相册里的照片
            // 注意:需要在pubspec.yaml中添加assets配置
            Container(
              height: 150,
              child: Image.asset(
                'assets/images/flutter_logo.png',
                fit: BoxFit.contain,
                errorBuilder: (context, error, stackTrace) {
                  return Container(
                    color: Colors.blue[100],
                    child: Center(
                      child: Icon(Icons.image, size: 50),
                    ),
                  );
                },
              ),
            ),
            
            SizedBox(height: 20),
            
            // 圆形头像 - 就像证件照
            CircleAvatar(
              radius: 50,
              backgroundImage: NetworkImage('https://picsum.photos/100/100'),
              child: Text('头像'), // 当图片加载失败时显示
            ),
            
            SizedBox(height: 20),
            
            // 不同的图片适应方式
            Text('不同的图片适应方式:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 10),
            
            Row(
              children: [
                Expanded(
                  child: Column(
                    children: [
                      Container(
                        height: 100,
                        color: Colors.grey[300],
                        child: Image.network(
                          'https://picsum.photos/200/300',
                          fit: BoxFit.cover, // 覆盖整个容器
                        ),
                      ),
                      Text('cover - 覆盖'),
                    ],
                  ),
                ),
                SizedBox(width: 10),
                Expanded(
                  child: Column(
                    children: [
                      Container(
                        height: 100,
                        color: Colors.grey[300],
                        child: Image.network(
                          'https://picsum.photos/200/300',
                          fit: BoxFit.contain, // 完整显示
                        ),
                      ),
                      Text('contain - 完整显示'),
                    ],
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

2.3 Icon Widget - 就像标识符号

Icon Widget就像现实中的各种符号:交通标志、商店标识、按钮图标等。

class IconExamples extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('图标展示大全')),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          children: [
            // 基础图标展示
            Text('基础图标:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Column(
                  children: [
                    Icon(Icons.home, size: 40, color: Colors.blue),
                    Text('首页'),
                  ],
                ),
                Column(
                  children: [
                    Icon(Icons.favorite, size: 40, color: Colors.red),
                    Text('喜欢'),
                  ],
                ),
                Column(
                  children: [
                    Icon(Icons.settings, size: 40, color: Colors.grey),
                    Text('设置'),
                  ],
                ),
                Column(
                  children: [
                    Icon(Icons.person, size: 40, color: Colors.green),
                    Text('个人'),
                  ],
                ),
              ],
            ),
            
            SizedBox(height: 32),
            
            // 不同大小的图标
            Text('不同大小的图标:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Icon(Icons.star, size: 20, color: Colors.orange),
                Icon(Icons.star, size: 30, color: Colors.orange),
                Icon(Icons.star, size: 40, color: Colors.orange),
                Icon(Icons.star, size: 50, color: Colors.orange),
              ],
            ),
            
            SizedBox(height: 32),
            
            // 带背景的图标
            Text('带背景的图标:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                // 圆形背景
                Container(
                  padding: EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    color: Colors.blue,
                    shape: BoxShape.circle,
                  ),
                  child: Icon(Icons.phone, color: Colors.white),
                ),
                
                // 方形背景
                Container(
                  padding: EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    color: Colors.green,
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: Icon(Icons.message, color: Colors.white),
                ),
                
                // 带边框的背景
                Container(
                  padding: EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.red, width: 2),
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: Icon(Icons.email, color: Colors.red),
                ),
              ],
            ),
            
            SizedBox(height: 32),
            
            // 常用图标集合
            Text('常用图标集合:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Wrap(
              spacing: 20,
              runSpacing: 20,
              children: [
                _buildIconWithLabel(Icons.add, '添加'),
                _buildIconWithLabel(Icons.delete, '删除'),
                _buildIconWithLabel(Icons.edit, '编辑'),
                _buildIconWithLabel(Icons.search, '搜索'),
                _buildIconWithLabel(Icons.share, '分享'),
                _buildIconWithLabel(Icons.download, '下载'),
                _buildIconWithLabel(Icons.upload, '上传'),
                _buildIconWithLabel(Icons.refresh, '刷新'),
              ],
            ),
          ],
        ),
      ),
    );
  }
  
  Widget _buildIconWithLabel(IconData icon, String label) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Icon(icon, size: 30, color: Colors.blue[700]),
        SizedBox(height: 4),
        Text(label, style: TextStyle(fontSize: 12)),
      ],
    );
  }
}

2.4 Container Widget - 就像万能盒子

Container就像现实中的各种容器:盒子、相框、房间等,可以装饰和包装其他物品。

class ContainerExamples extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('容器展示大全')),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(16),
        child: Column(
          children: [
            // 基础容器 - 就像一个简单的盒子
            Text('基础容器:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Container(
              width: 200,
              height: 100,
              color: Colors.blue[100],
              child: Center(
                child: Text('我是一个简单的盒子'),
              ),
            ),
            
            SizedBox(height: 32),
            
            // 带装饰的容器 - 就像装饰过的礼品盒
            Text('装饰容器:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Container(
              width: 200,
              height: 100,
              decoration: BoxDecoration(
                color: Colors.pink[100],
                border: Border.all(color: Colors.pink, width: 2),
                borderRadius: BorderRadius.circular(12),
                boxShadow: [
                  BoxShadow(
                    color: Colors.grey.withOpacity(0.5),
                    spreadRadius: 2,
                    blurRadius: 5,
                    offset: Offset(0, 3),
                  ),
                ],
              ),
              child: Center(
                child: Text('我是装饰过的盒子'),
              ),
            ),
            
            SizedBox(height: 32),
            
            // 带内边距的容器 - 就像盒子里的缓冲材料
            Text('带内边距的容器:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Container(
              width: 200,
              height: 120,
              color: Colors.green[100],
              padding: EdgeInsets.all(20), // 内边距
              child: Container(
                color: Colors.green[300],
                child: Center(
                  child: Text('内容'),
                ),
              ),
            ),
            
            SizedBox(height: 32),
            
            // 带外边距的容器 - 就像盒子周围的空间
            Text('带外边距的容器:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Container(
              color: Colors.grey[200],
              child: Container(
                width: 150,
                height: 80,
                margin: EdgeInsets.all(20), // 外边距
                color: Colors.orange[200],
                child: Center(
                  child: Text('我有外边距'),
                ),
              ),
            ),
            
            SizedBox(height: 32),
            
            // 不同形状的容器
            Text('不同形状的容器:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                // 圆形容器
                Container(
                  width: 80,
                  height: 80,
                  decoration: BoxDecoration(
                    color: Colors.red[200],
                    shape: BoxShape.circle,
                  ),
                  child: Center(child: Text('圆形')),
                ),
                
                // 圆角矩形容器
                Container(
                  width: 80,
                  height: 80,
                  decoration: BoxDecoration(
                    color: Colors.blue[200],
                    borderRadius: BorderRadius.circular(20),
                  ),
                  child: Center(child: Text('圆角')),
                ),
                
                // 椭圆形容器
                Container(
                  width: 100,
                  height: 60,
                  decoration: BoxDecoration(
                    color: Colors.purple[200],
                    borderRadius: BorderRadius.circular(30),
                  ),
                  child: Center(child: Text('椭圆')),
                ),
              ],
            ),
            
            SizedBox(height: 32),
            
            // 渐变背景容器 - 就像彩虹色的盒子
            Text('渐变背景容器:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Container(
              width: 200,
              height: 100,
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [Colors.blue, Colors.purple],
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                ),
                borderRadius: BorderRadius.circular(12),
              ),
              child: Center(
                child: Text(
                  '渐变背景',
                  style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

2.5 Button系列组件 - 就像各种开关和按钮

按钮就像现实中的各种开关、按键:电灯开关、电梯按钮、遥控器按键等。

class ButtonExamples extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('按钮展示大全')),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // ElevatedButton - 就像立体的按钮
            Text('立体按钮 (ElevatedButton):', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            ElevatedButton(
              onPressed: () {
                _showMessage(context, '你点击了立体按钮!');
              },
              child: Text('点击我'),
            ),
            
            SizedBox(height: 16),
            
            // 自定义样式的立体按钮
            ElevatedButton(
              onPressed: () {
                _showMessage(context, '你点击了自定义按钮!');
              },
              style: ElevatedButton.styleFrom(
                backgroundColor: Colors.red,
                foregroundColor: Colors.white,
                padding: EdgeInsets.symmetric(horizontal: 32, vertical: 16),
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(20),
                ),
              ),
              child: Text('自定义样式按钮'),
            ),
            
            SizedBox(height: 32),
            
            // TextButton - 就像文字链接
            Text('文字按钮 (TextButton):', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            TextButton(
              onPressed: () {
                _showMessage(context, '你点击了文字按钮!');
              },
              child: Text('我是文字按钮'),
            ),
            
            TextButton(
              onPressed: () {
                _showMessage(context, '你点击了彩色文字按钮!');
              },
              style: TextButton.styleFrom(
                foregroundColor: Colors.purple,
                textStyle: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
              ),
              child: Text('彩色文字按钮'),
            ),
            
            SizedBox(height: 32),
            
            // OutlinedButton - 就像有边框的按钮
            Text('边框按钮 (OutlinedButton):', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            OutlinedButton(
              onPressed: () {
                _showMessage(context, '你点击了边框按钮!');
              },
              child: Text('边框按钮'),
            ),
            
            OutlinedButton(
              onPressed: () {
                _showMessage(context, '你点击了自定义边框按钮!');
              },
              style: OutlinedButton.styleFrom(
                foregroundColor: Colors.green,
                side: BorderSide(color: Colors.green, width: 2),
                padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
              ),
              child: Text('自定义边框按钮'),
            ),
            
            SizedBox(height: 32),
            
            // IconButton - 就像只有图标的按钮
            Text('图标按钮 (IconButton):', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                IconButton(
                  onPressed: () {
                    _showMessage(context, '你点击了喜欢按钮!');
                  },
                  icon: Icon(Icons.favorite),
                  color: Colors.red,
                  iconSize: 30,
                ),
                
                IconButton(
                  onPressed: () {
                    _showMessage(context, '你点击了分享按钮!');
                  },
                  icon: Icon(Icons.share),
                  color: Colors.blue,
                  iconSize: 30,
                ),
                
                IconButton(
                  onPressed: () {
                    _showMessage(context, '你点击了设置按钮!');
                  },
                  icon: Icon(Icons.settings),
                  color: Colors.grey,
                  iconSize: 30,
                ),
              ],
            ),
            
            SizedBox(height: 32),
            
            // FloatingActionButton - 就像悬浮的圆形按钮
            Text('悬浮按钮 (FloatingActionButton):', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            Center(
              child: FloatingActionButton(
                onPressed: () {
                  _showMessage(context, '你点击了悬浮按钮!');
                },
                child: Icon(Icons.add),
                backgroundColor: Colors.blue,
              ),
            ),
            
            SizedBox(height: 16),
            
            // 扩展的悬浮按钮
            Center(
              child: FloatingActionButton.extended(
                onPressed: () {
                  _showMessage(context, '你点击了扩展悬浮按钮!');
                },
                icon: Icon(Icons.edit),
                label: Text('编辑'),
                backgroundColor: Colors.green,
              ),
            ),
            
            SizedBox(height: 32),
            
            // 带图标的按钮
            Text('带图标的按钮:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            ElevatedButton.icon(
              onPressed: () {
                _showMessage(context, '你点击了下载按钮!');
              },
              icon: Icon(Icons.download),
              label: Text('下载'),
            ),
            
            SizedBox(height: 16),
            
            OutlinedButton.icon(
              onPressed: () {
                _showMessage(context, '你点击了上传按钮!');
              },
              icon: Icon(Icons.upload),
              label: Text('上传'),
            ),
            
            SizedBox(height: 32),
            
            // 禁用状态的按钮
            Text('禁用状态的按钮:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 16),
            
            ElevatedButton(
              onPressed: null, // null表示禁用
              child: Text('禁用的按钮'),
            ),
            
            SizedBox(height: 16),
            
            OutlinedButton(
              onPressed: null,
              child: Text('禁用的边框按钮'),
            ),
          ],
        ),
      ),
    );
  }
  
  void _showMessage(BuildContext context, String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        duration: Duration(seconds: 2),
      ),
    );
  }
}

🎯 实践练习

练习1:创建个人名片应用

class PersonalCardApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '个人名片',
      home: PersonalCard(),
    );
  }
}

class PersonalCard extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blue[50],
      appBar: AppBar(
        title: Text('我的名片'),
        backgroundColor: Colors.blue[600],
        elevation: 0,
      ),
      body: Center(
        child: Container(
          margin: EdgeInsets.all(20),
          padding: EdgeInsets.all(24),
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(16),
            boxShadow: [
              BoxShadow(
                color: Colors.grey.withOpacity(0.3),
                spreadRadius: 2,
                blurRadius: 10,
                offset: Offset(0, 4),
              ),
            ],
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              // 头像
              CircleAvatar(
                radius: 50,
                backgroundColor: Colors.blue[200],
                child: Icon(
                  Icons.person,
                  size: 60,
                  color: Colors.blue[600],
                ),
              ),
              
              SizedBox(height: 20),
              
              // 姓名
              Text(
                '张三',
                style: TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                  color: Colors.grey[800],
                ),
              ),
              
              SizedBox(height: 8),
              
              // 职位
              Text(
                'Flutter开发工程师',
                style: TextStyle(
                  fontSize: 16,
                  color: Colors.grey[600],
                ),
              ),
              
              SizedBox(height: 20),
              
              // 联系方式
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  _buildContactButton(
                    icon: Icons.phone,
                    label: '电话',
                    color: Colors.green,
                  ),
                  _buildContactButton(
                    icon: Icons.email,
                    label: '邮箱',
                    color: Colors.blue,
                  ),
                  _buildContactButton(
                    icon: Icons.location_on,
                    label: '地址',
                    color: Colors.red,
                  ),
                ],
              ),
              
              SizedBox(height: 20),
              
              // 个人简介
              Container(
                padding: EdgeInsets.all(16),
                decoration: BoxDecoration(
                  color: Colors.grey[100],
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Text(
                  '热爱编程,专注于移动应用开发。'
                  '拥有3年Flutter开发经验,'
                  '致力于创造优秀的用户体验。',
                  style: TextStyle(
                    fontSize: 14,
                    color: Colors.grey[700],
                    height: 1.5,
                  ),
                  textAlign: TextAlign.center,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
  
  Widget _buildContactButton({
    required IconData icon,
    required String label,
    required Color color,
  }) {
    return Column(
      children: [
        Container(
          padding: EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: color.withOpacity(0.1),
            borderRadius: BorderRadius.circular(8),
          ),
          child: Icon(icon, color: color, size: 24),
        ),
        SizedBox(height: 4),
        Text(
          label,
          style: TextStyle(
            fontSize: 12,
            color: Colors.grey[600],
          ),
        ),
      ],
    );
  }
}

学习总结

通过这一章的学习,你已经掌握了:

  1. Widget概念:理解了一切皆Widget的思想
  2. StatelessWidget vs StatefulWidget:知道了静态和动态组件的区别
  3. 基础Widget:学会了Text、Image、Icon、Container、Button的使用

恭喜你完成了Flutter基础概念的学习!🎉 现在你已经掌握了Flutter开发的基础积木,可以开始构建更复杂的应用了!

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐