Flutter(十)Container Center Align

Container

默认情况下 transform 的旋转原点是 左上角 ( Offset.zero )。要让 Container 绕中心旋转 ,需要设置 transformAlignment 属性.

scala 复制代码
import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(
    MaterialApp(
      theme: ThemeData(scaffoldBackgroundColor: Colors.grey),
      home: Scaffold(body: MainPage3()),
    ),
  );
}

class MainPage extends StatelessWidget {
  const MainPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // 如果不设置宽高,会覆盖整个屏幕
    return Container(
      width: 100,
      // height: 100,
      color: Colors.green,
    );
  }
}

class MainPage1 extends StatelessWidget {
  const MainPage1({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // 如果不设置高度,宽度固定100,高度覆盖整个屏幕
    // 同理,如果高度固定,宽度会填充整个屏幕
    return Container(
      // width: 100,
      height: 100,
      color: Colors.green,
    );
  }
}

// Color和 decoration只能同时有一个,就算外面有color里面的decoration不设置color也会报错
class MainPage2 extends StatelessWidget {
  const MainPage2({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // 如果不设置高度,宽度固定100,高度覆盖整个屏幕
    // 同理,如果高度固定,宽度会填充整个屏幕
    return Container(
      width: 100,
      height: 100,
      // color: Colors.green,
      decoration: BoxDecoration(
        color: Colors.red,
        // 设置圆角
        borderRadius: BorderRadius.circular(20),
      ),
      child: Text("data"),
    );
  }
}

class MainPage3 extends StatelessWidget {
  const MainPage3({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 200,
      margin: EdgeInsets.all(50),
      height: 200,
      decoration: BoxDecoration(
        color: Colors.cyan,
        borderRadius: BorderRadius.circular(20),
        border: Border.all(width: 3, color: Colors.white),
      ),
      // 3.14为180度旋转
      transform: Matrix4.rotationZ(3.14 / 4),
      transformAlignment: Alignment.center, // ✅ 旋转原点设为中心(默认是左上角)
      alignment: Alignment.center,
      child: Text("hello"),
    );
  }
}

Container进阶

less 复制代码
import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Container 知识体系',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const ContainerGuide(),
    );
  }
}

// ═══════════════════════════════════════════════════════════
// Container 知识体系总览页
// ═══════════════════════════════════════════════════════════
class ContainerGuide extends StatelessWidget {
  const ContainerGuide({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Container 知识体系')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          // ── 本质说明 ──
          Container(
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Colors.blue.shade50,
              borderRadius: BorderRadius.circular(8),
            ),
            child: const Text(
              '📖 Container 本质:\n'
              'Container 是一个「复合 Widget」,本身不渲染任何内容。\n'
              '它会根据你设置的属性,内部组合 Padding / DecoratedBox /\n'
              'ConstrainedBox / Transform / Align / ClipPath 等基础 Widget。\n'
              '不设任何属性且 child 为 null 时,Container 会尽可能小(不占空间)。',
              style: TextStyle(fontSize: 13, height: 1.6),
            ),
          ),
          const SizedBox(height: 16),

          // ── 章节 1:基础属性 ──
          _Section(title: '1. 基础属性(color / width / height / child)'),
          _BasicDemo(),

          // ── 章节 2:margin vs padding ──
          _Section(title: '2. margin(外边距)vs padding(内边距)'),
          _MarginPaddingDemo(),

          // ── 章节 3:alignment ──
          _Section(title: '3. alignment(子组件对齐)'),
          _AlignmentDemo(),

          // ── 章节 4:decoration BoxDecoration ──
          _Section(title: '4. decoration(BoxDecoration 装饰)'),
          _DecorationDemo(),

          // ── 章节 5:gradient 渐变 ──
          _Section(title: '5. gradient(渐变背景)'),
          _GradientDemo(),

          // ── 章节 6:boxShadow 阴影 ──
          _Section(title: '6. boxShadow(阴影)'),
          _ShadowDemo(),

          // ── 章节 7:shape 形状 ──
          _Section(title: '7. shape(矩形 / 圆形)'),
          _ShapeDemo(),

          // ── 章节 8:border + borderRadius 边框 ──
          _Section(title: '8. border & borderRadius(边框与圆角)'),
          _BorderDemo(),

          // ── 章节 9:transform 变换 ──
          _Section(title: '9. transform(矩阵变换)'),
          _TransformDemo(),

          // ── 章节 10:constraints 约束 ──
          _Section(title: '10. constraints(BoxConstraints 约束)'),
          _ConstraintsDemo(),

          // ── 章节 11:foregroundDecoration 前景装饰 ──
          _Section(title: '11. foregroundDecoration(前景装饰)'),
          _ForegroundDemo(),

          // ── 章节 12:clipBehavior 裁剪 ──
          _Section(title: '12. clipBehavior(裁剪行为)'),
          _ClipDemo(),

          // ── 章节 13:尺寸规则 ──
          _Section(title: '13. Container 尺寸规则(无 child 时的撑满行为)'),
          _SizeRuleDemo(),

          // ── 章节 14:包裹顺序 ──
          _Section(title: '14. Container 内部包裹顺序(重要!)'),
          _WrapOrderDemo(),
        ],
      ),
    );
  }
}

// 通用章节标题组件
class _Section extends StatelessWidget {
  final String title;
  const _Section({required this.title});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: 24, bottom: 12),
      child: Text(title, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
    );
  }
}

// ─────────────────────────────────────────────
// 1. 基础属性
// ─────────────────────────────────────────────
// color:背景色(注意:与 decoration 互斥,不能同时设置)
// width / height:固定尺寸
// child:唯一子组件
// ─────────────────────────────────────────────
class _BasicDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // 只设 color:会撑满父级可用空间(因为无 child 无尺寸约束时 Container 最大化)
        Container(
          color: Colors.red.shade200,
          width: double.infinity, // 撑满宽度
          height: 40,
          alignment: Alignment.center,
          child: const Text('color + width + height + child'),
        ),
        const SizedBox(height: 8),
        // ✅ 推荐:用 decoration 替代 color(更灵活,能加边框/圆角/渐变)
        Container(
          width: 200,
          height: 60,
          alignment: Alignment.center,
          decoration: BoxDecoration(
            color: Colors.green.shade200, // 颜色放在 decoration 里
          ),
          child: const Text('推荐写法:颜色放 decoration'),
        ),
      ],
    );
  }
}

// ─────────────────────────────────────────────
// 2. margin vs padding
// ─────────────────────────────────────────────
// margin:外边距,Container 与父级的距离(在 decoration 外面)
// padding:内边距,child 与 decoration 的距离(在 decoration 里面)
// 包裹顺序:margin → decoration → padding → child
// ─────────────────────────────────────────────
class _MarginPaddingDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 外层灰色 = 父容器,用于观察 margin
        Container(
          color: Colors.grey.shade300,
          child: Container(
            margin: const EdgeInsets.all(20), // 外边距:与灰色父级隔开 20
            padding: const EdgeInsets.all(16), // 内边距:文字与蓝色边隔开 16
            color: Colors.blue.shade200,
            child: const Text('蓝色=Container本体\n灰色=margin 外露区域\n文字到蓝边=padding'),
          ),
        ),
        const SizedBox(height: 8),
        const Text(
          'margin:decoration 外面的空白(灰色区域)\n'
          'padding:decoration 里面的空白(文字到蓝边距离)',
          style: TextStyle(fontSize: 12, color: Colors.grey),
        ),
      ],
    );
  }
}

// ─────────────────────────────────────────────
// 3. alignment
// ─────────────────────────────────────────────
// alignment:决定 child 在 Container 内的对齐位置
// 设置后 Container 会撑满可用空间(像 Align 一样)
// 常用:Alignment.center / topLeft / bottomRight / centerLeft ...
// ─────────────────────────────────────────────
class _AlignmentDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 120,
      width: double.infinity,
      color: Colors.orange.shade100,
      alignment: Alignment.bottomRight, // 子组件右下角对齐
      child: const Text('我在右下角'),
    );
  }
}

// ─────────────────────────────────────────────
// 4. decoration(BoxDecoration)
// ─────────────────────────────────────────────
// BoxDecoration 是最常用的装饰,支持:
//   color / border / borderRadius / gradient / boxShadow / image / shape
// ⚠️ decoration.color 与 Container.color 互斥,不能同时设置
// ─────────────────────────────────────────────
class _DecorationDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.all(16),
      // BoxDecoration 集中管理所有视觉装饰
      decoration: BoxDecoration(
        color: Colors.purple.shade100,        // 背景色
        borderRadius: BorderRadius.circular(12), // 圆角
        border: Border.all(                     // 边框
          color: Colors.purple,
          width: 2,
        ),
      ),
      child: const Text('decoration 同时设置:背景色 + 圆角 + 边框'),
    );
  }
}

// ─────────────────────────────────────────────
// 5. gradient 渐变
// ─────────────────────────────────────────────
// 三种渐变:
//   LinearGradient  线性渐变(最常用)
//   RadialGradient  径向渐变(从中心向外)
//   SweepGradient   扫描渐变(雷达图效果)
// ⚠️ gradient 会覆盖 color(gradient 优先级更高)
// ─────────────────────────────────────────────
class _GradientDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 线性渐变
        Container(
          height: 60,
          width: double.infinity,
          alignment: Alignment.center,
          decoration: const BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment.centerLeft,    // 起点位置
              end: Alignment.centerRight,      // 终点位置
              colors: [Colors.red, Colors.blue], // 颜色列表
              stops: [0.0, 1.0],               // 每个颜色的位置(0~1)
            ),
          ),
          child: const Text('LinearGradient 线性渐变', style: TextStyle(color: Colors.white)),
        ),
        const SizedBox(height: 8),
        // 径向渐变
        Container(
          height: 80,
          width: 80,
          decoration: const BoxDecoration(
            shape: BoxShape.circle,
            gradient: RadialGradient(
              colors: [Colors.yellow, Colors.orange, Colors.red],
            ),
          ),
        ),
      ],
    );
  }
}

// ─────────────────────────────────────────────
// 6. boxShadow 阴影
// ─────────────────────────────────────────────
// boxShadow 是一个 List,可以叠加多个阴影
// BoxShadow 属性:
//   color     阴影颜色
//   blurRadius 模糊半径(越大越虚)
//   spreadRadius 扩展半径(正值扩大,负值缩小)
//   offset    偏移量(dx, dy)
// ⚠️ 阴影需要 backgroundColor 或 elevation 配合才明显
// ─────────────────────────────────────────────
class _ShadowDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.all(20),
      margin: const EdgeInsets.all(8), // 留白让阴影可见
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(12),
        boxShadow: [
          // 第一层:深色近阴影
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.2),
            blurRadius: 8,        // 模糊程度
            spreadRadius: 2,      // 阴影扩散
            offset: const Offset(0, 4), // x=0(不左右偏), y=4(向下偏)
          ),
          // 第二层:浅色远阴影(可叠加多层制造立体感)
          BoxShadow(
            color: Colors.blue.withValues(alpha: 0.1),
            blurRadius: 20,
            spreadRadius: 0,
            offset: const Offset(0, 0),
          ),
        ],
      ),
      child: const Text('boxShadow 可叠加多层\n制造立体卡片效果'),
    );
  }
}

// ─────────────────────────────────────────────
// 7. shape 形状
// ─────────────────────────────────────────────
// shape 有两个值:
//   BoxShape.rectangle  矩形(默认)
//   BoxShape.circle      圆形
// ⚠️ 设为 circle 时,borderRadius 会被忽略
// ─────────────────────────────────────────────
class _ShapeDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        // 矩形(默认)
        Container(
          width: 80,
          height: 80,
          alignment: Alignment.center,
          decoration: BoxDecoration(
            shape: BoxShape.rectangle, // 默认值
            color: Colors.teal,
            borderRadius: BorderRadius.circular(12),
          ),
          child: const Text('矩形', style: TextStyle(color: Colors.white)),
        ),
        const SizedBox(width: 16),
        // 圆形
        Container(
          width: 80,
          height: 80,
          alignment: Alignment.center,
          decoration: const BoxDecoration(
            shape: BoxShape.circle, // 设为圆形
            color: Colors.indigo,
          ),
          child: const Text('圆形', style: TextStyle(color: Colors.white)),
        ),
      ],
    );
  }
}

// ─────────────────────────────────────────────
// 8. border & borderRadius
// ─────────────────────────────────────────────
// border:边框,支持四边统一或分别设置
//   Border.all()              四边相同
//   Border(top:..., bottom:...) 各边不同
// borderRadius:圆角,支持统一或分别设置
//   BorderRadius.all(Radius.circular(12))  四角相同
//   BorderRadius.only(topLeft:...)         指定角
// ⚠️ 圆形(shape: circle)下 borderRadius 无效
// ─────────────────────────────────────────────
class _BorderDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // ① 四边相同边框 + 统一圆角(✅ 兼容)
        Container(
          width: double.infinity,
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: Colors.yellow.shade100,
            border: Border.all(color: Colors.orange, width: 2),
            borderRadius: BorderRadius.circular(8),
          ),
          child: const Text('① Border.all 四边相同 + 圆角(兼容)'),
        ),
        const SizedBox(height: 8),
        // ② 各边不同 border(⚠️ 不能配 borderRadius,否则报错)
        //    错误信息:A borderRadius can only be given on borders with uniform colors
        Container(
          width: double.infinity,
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: Colors.cyan.shade50,
            border: const Border(
              top: BorderSide(color: Colors.red, width: 3),
              bottom: BorderSide(color: Colors.blue, width: 3),
            ),
            // ⚠️ 这里不能加 borderRadius,因为各边颜色不同
          ),
          child: const Text('② 各边不同 border(不能配圆角)'),
        ),
        const SizedBox(height: 8),
        // ③ 指定角圆角 + 统一颜色 border(✅ 兼容)
        Container(
          width: double.infinity,
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: Colors.green.shade50,
            border: Border.all(color: Colors.green, width: 2),
            borderRadius: const BorderRadius.only(
              topLeft: Radius.circular(16),
              bottomRight: Radius.circular(16),
            ),
          ),
          child: const Text('③ 指定角圆角 + 统一颜色 border(兼容)'),
        ),
      ],
    );
  }
}

// ─────────────────────────────────────────────
// 9. transform 变换
// ─────────────────────────────────────────────
// transform:通过 Matrix4 矩阵做变换(平移/旋转/缩放/倾斜)
// 常用 Matrix4 方法:
//   Matrix4.translationValues(x, y, z)  平移
//   Matrix4.rotationZ(radians)          绕 Z 轴旋转
//   Matrix4.scale(x, y, z)              缩放
// transformAlignment:变换的原点(默认中心)
// ⚠️ transform 不影响布局(不影响占位空间),只是视觉变换
// ─────────────────────────────────────────────
class _TransformDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        // 平移
        Container(
          width: 60,
          height: 60,
          color: Colors.green.shade300,
          alignment: Alignment.center,
          transform: Matrix4.translationValues(10, -10, 0), // 右移10,上移10
          child: const Text('平移', style: TextStyle(fontSize: 11)),
        ),
        const SizedBox(width: 30),
        // 旋转
        Container(
          width: 60,
          height: 60,
          color: Colors.red.shade300,
          alignment: Alignment.center,
          transform: Matrix4.rotationZ(0.3), // 旋转 0.3 弧度
          child: const Text('旋转', style: TextStyle(fontSize: 11)),
        ),
        const SizedBox(width: 30),
        // 缩放
        Container(
          width: 60,
          height: 60,
          color: Colors.purple.shade300,
          alignment: Alignment.center,
          transform: Matrix4.diagonal3Values(1.3, 1.3, 1.0), // 放大 1.3 倍
          child: const Text('缩放', style: TextStyle(fontSize: 11)),
        ),
      ],
    );
  }
}

// ─────────────────────────────────────────────
// 10. constraints 约束
// ─────────────────────────────────────────────
// constraints:BoxConstraints,限制 Container 的尺寸范围
//   minWidth / maxWidth / minHeight / maxHeight
// 与 width/height 的区别:
//   width/height 是固定值(本质是 constraints 的 min=max)
//   constraints 是范围,更灵活
// 优先级:constraints > width/height
// ─────────────────────────────────────────────
class _ConstraintsDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      // 约束:最小高度 50,最大高度 100(随 child 内容在此范围)
      constraints: const BoxConstraints(
        minWidth: 100,
        maxWidth: 300,
        minHeight: 50,
        maxHeight: 100,
      ),
      color: Colors.pink.shade100,
      alignment: Alignment.center,
      child: const Text('constraints 限制尺寸范围'),
    );
  }
}

// ─────────────────────────────────────────────
// 11. foregroundDecoration 前景装饰
// ─────────────────────────────────────────────
// foregroundDecoration:绘制在 child 之上的装饰(盖在 child 上面)
// 与 decoration 区别:
//   decoration:背景层(在 child 下面)
//   foregroundDecoration:前景层(在 child 上面)
// 常用于:遮罩、水印、叠加边框
// ─────────────────────────────────────────────
class _ForegroundDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.all(16),
      // 背景装饰:在 child 下面
      decoration: BoxDecoration(
        color: Colors.blue.shade100,
        borderRadius: BorderRadius.circular(8),
      ),
      // 前景装饰:在 child 上面(盖住文字)
      foregroundDecoration: BoxDecoration(
        border: Border.all(color: Colors.red, width: 3),
        borderRadius: BorderRadius.circular(8),
        color: Colors.black.withValues(alpha: 0.2), // 半透明遮罩盖在文字上
      ),
      child: const Text('红色边框+半透明遮罩 = foregroundDecoration\n(绘制在 child 之上)'),
    );
  }
}

// ─────────────────────────────────────────────
// 12. clipBehavior 裁剪
// ─────────────────────────────────────────────
// clipBehavior:当内容超出边界时是否裁剪
//   Clip.none       不裁剪(默认,超出部分可见)
//   Clip.hardEdge   硬边缘裁剪(最快,边缘略锯齿)
//   Clip.antiAlias  抗锯齿裁剪(边缘平滑,稍慢)
//   Clip.antiAliasWithSaveLayer 最平滑(最慢,少用)
// 场景:圆角容器内放图片/超大内容时需要裁剪
// ─────────────────────────────────────────────
class _ClipDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        // 不裁剪:内容溢出圆角
        Container(
          width: 80,
          height: 80,
          decoration: BoxDecoration(
            color: Colors.red,
            borderRadius: BorderRadius.circular(20),
          ),
          clipBehavior: Clip.none, // 默认,内容会溢出圆角
          child: Container(
            margin: const EdgeInsets.all(20),
            color: Colors.yellow,
          ),
        ),
        const SizedBox(width: 16),
        // 裁剪:内容被圆角裁剪
        Container(
          width: 80,
          height: 80,
          decoration: BoxDecoration(
            color: Colors.red,
            borderRadius: BorderRadius.circular(20),
          ),
          clipBehavior: Clip.antiAlias, // 内容被圆角裁剪
          child: Container(
            margin: const EdgeInsets.all(20),
            color: Colors.yellow,
          ),
        ),
        const SizedBox(width: 8),
        const Text('左:Clip.none\n右:Clip.antiAlias', style: TextStyle(fontSize: 11)),
      ],
    );
  }
}

// ─────────────────────────────────────────────
// 13. 尺寸规则
// ─────────────────────────────────────────────
// Container 的尺寸由「约束 + 属性 + child」共同决定:
// ① 有 child:默认跟随 child 尺寸
// ② 无 child 无尺寸:撑满父级可用空间(最大化)
// ③ 有 width/height:使用指定值
// ④ constraints 优先级最高
// ─────────────────────────────────────────────
class _SizeRuleDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // 无 child 无尺寸:撑满高度(这里被外层 ListView 限制为不定高,所以需指定)
        Container(
          width: double.infinity,
          height: 40,
          color: Colors.amber,
          alignment: Alignment.center,
          child: const Text('无 child + 指定 height → 用指定值'),
        ),
        const SizedBox(height: 8),
        // 有 child:跟随 child 尺寸
        Container(
          color: Colors.lightGreen,
          child: const Padding(
            padding: EdgeInsets.all(8),
            child: Text('有 child → 跟随 child 尺寸(紧贴内容)'),
          ),
        ),
      ],
    );
  }
}

// ─────────────────────────────────────────────
// 14. 内部包裹顺序(核心知识点!)
// ─────────────────────────────────────────────
// Container 内部实际生成的 Widget 树(从外到内):
//
//   margin (Padding)
//     └─ transform (Transform)
//          └─ decoration (DecoratedBox)
//               └─ foregroundDecoration + clip (ClipPath)
//                    └─ constraints (ConstrainedBox)
//                         └─ padding (Padding)
//                              └─ alignment (Align)
//                                   └─ child
//
// 这就是为什么:
//   - margin 在装饰外面,padding 在装饰里面
//   - transform 不影响布局(在最外层视觉变换)
//   - decoration 在 padding 外(背景包含 padding 区域)
// ─────────────────────────────────────────────
class _WrapOrderDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      // ① 最外层:margin(外边距)
      margin: const EdgeInsets.all(16),
      // ② transform(视觉变换,不影响布局)
      transform: Matrix4.identity(),
      // ③ decoration(背景装饰,包含 padding 区域)
      decoration: BoxDecoration(
        color: Colors.indigo.shade100,
        border: Border.all(color: Colors.indigo, width: 2),
        borderRadius: BorderRadius.circular(8),
      ),
      // ④ constraints(尺寸约束)
      constraints: const BoxConstraints(minHeight: 80),
      // ⑤ padding(内边距,在装饰里面)
      padding: const EdgeInsets.all(16),
      // ⑥ alignment(child 对齐)
      alignment: Alignment.center,
      // ⑦ clipBehavior(裁剪)
      clipBehavior: Clip.antiAlias,
      // ⑧ 最内层:child
      child: const Text(
        'margin → transform → decoration\n→ clip → constraints\n→ padding → alignment → child',
        textAlign: TextAlign.center,
        style: TextStyle(fontSize: 12),
      ),
    );
  }
}

Center

对齐,用Center组件,和用Container的对齐属性。性能一致。

Center本质就是Align。

scala 复制代码
import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(
    MaterialApp(
      theme: ThemeData(scaffoldBackgroundColor: Colors.grey),
      home: Scaffold(body: MainPage2()),
    ),
  );
}

class MainPage extends StatelessWidget {
  const MainPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // center不能设置宽高,不能设置背景颜色
    return Center(child: Text("hello"));
  }
}

class MainPage1 extends StatelessWidget {
  const MainPage1({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // 通过Container设置大小
    return Center(
      child: Container(
        width: 100,
        height: 100,
        color: Colors.blueGrey,
        alignment: .center,
        child: Text("hello"),
      ),
    );
  }
}

class MainPage2 extends StatelessWidget {
  const MainPage2({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // 通过Container设置大小
    return Center(
      child: Container(
        width: 100,
        height: 100,
        color: Colors.blueGrey,
        // alignment: .center,
        child: Center(child: Text("hello")),
      ),
    );
  }
}

factor等比例缩放。

less 复制代码
import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(
    MaterialApp(
      theme: ThemeData(
        scaffoldBackgroundColor: const Color.fromARGB(255, 223, 212, 212),
      ),
      home: Scaffold(body: MainPage()),
    ),
  );
}

class MainPage extends StatelessWidget {
  const MainPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.black,
      child: Container(
        color: Colors.white,
        child: Center(
          widthFactor: 2,
          heightFactor: 2,
          child: Container(width: 100, height: 100, color: Colors.green),
        ),
      ),
    );
  }
}

Center进阶

less 复制代码
import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(const MaterialApp(home: HomePage()));
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Center 全方位知识点')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: const [
          _Section1_WhatIsCenter(),
          _Section2_ShrinkWrapMechanism(),
          _Section3_TightVsLooseConstraint(),
          _Section4_WidthFactorDetail(),
          _Section5_HeightFactorDetail(),
          _Section6_InRowColumn(),
          _Section7_CenterVsAlign(),
          _Section8_CenterVsContainer(),
          _Section9_CommonUsage(),
          _Section10_Summary(),
        ],
      ),
    );
  }
}

// ────────────────────────────────────────────────────────────────
// ① 知识点 1:Center 的本质 ------ Align 的子类,固定居中
// ────────────────────────────────────────────────────────────────
class _Section1_WhatIsCenter extends StatelessWidget {
  const _Section1_WhatIsCenter();

  @override
  Widget build(BuildContext context) {
    return _Card(
      title: '① Center 的本质',
      subtitle: 'Center = Align(alignment: Alignment.center)',
      children: [
        const Text(
          '源码定义(简化):\n'
          'class Center extends Align {\n'
          '  const Center({ super.key, super.widthFactor,\n'
          '    super.heightFactor, super.child })\n'
          '    : super(alignment: Alignment.center);\n'
          '}\n\n'
          'Center 没有任何额外逻辑,就是 Align 写死了\n'
          'alignment.center 的语法糖。',
          style: TextStyle(fontSize: 12, fontFamily: 'monospace'),
        ),
        const SizedBox(height: 8),
        // 直接验证:两种写法等价
        Row(
          children: [
            Expanded(
              child: Container(
                height: 100,
                color: Colors.blue.shade50,
                child: const Center(child: Text('Center 写法')),
              ),
            ),
            const SizedBox(width: 8),
            Expanded(
              child: Container(
                height: 100,
                color: Colors.green.shade50,
                child: const Align(
                  alignment: Alignment.center,
                  child: Text('Align 写法'),
                ),
              ),
            ),
          ],
        ),
        const SizedBox(height: 4),
        const Text('↑ 两者渲染结果完全相同',
            style: TextStyle(fontSize: 11, color: Colors.grey)),
      ],
    );
  }
}

// ────────────────────────────────────────────────────────────────
// ② 知识点 2:核心机制 ------ shrinkWrap 逻辑(来自源码)
// ────────────────────────────────────────────────────────────────
class _Section2_ShrinkWrapMechanism extends StatelessWidget {
  const _Section2_ShrinkWrapMechanism();

  @override
  Widget build(BuildContext context) {
    return _Card(
      title: '② 核心机制:shrinkWrap 逻辑',
      subtitle: '决定 Center 是"撑满"还是"跟随 child"',
      children: [
        const Text(
          '源码(shifted_box.dart:478-497):\n\n'
          'shrinkWrapWidth  = widthFactor  != null || maxWidth  == ∞\n'
          'shrinkWrapHeight = heightFactor != null || maxHeight == ∞\n\n'
          'size = constrain(Size(\n'
          '  shrinkWrapWidth  ? child.w * factor : ∞,\n'
          '  shrinkWrapHeight ? child.h * factor : ∞,\n'
          '))\n\n'
          '┌───────────────┬────────────────────┬──────────────────┐\n'
          '│ 条件          │ shrinkWrap         │ Center 尺寸       │\n'
          '├───────────────┼────────────────────┼──────────────────┤\n'
          '│ 有 factor     │ true               │ child × factor   │\n'
          '│ 无 factor +   │ false              │ expand 到约束 max │\n'
          '│ 有界约束      │                    │                  │\n'
          '│ 无 factor +   │ true(因为 max=∞)  │ child 尺寸       │\n'
          '│ 无界约束      │                    │                  │\n'
          '└───────────────┴────────────────────┴──────────────────┘',
          style: TextStyle(fontSize: 11, fontFamily: 'monospace'),
        ),
      ],
    );
  }
}

// ────────────────────────────────────────────────────────────────
// ③ 知识点 3:紧密约束 vs 宽松约束下的行为对比
// ────────────────────────────────────────────────────────────────
class _Section3_TightVsLooseConstraint extends StatelessWidget {
  const _Section3_TightVsLooseConstraint();

  @override
  Widget build(BuildContext context) {
    return _Card(
      title: '③ 紧密约束 vs 宽松约束',
      subtitle: '约束类型决定 Center 能否自由决定尺寸',
      children: [
        // ── 紧密约束场景 ──
        const Text('场景 A:紧密约束(Container 有固定尺寸)',
            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12)),
        const Text('constraints 是 tight → Center 被迫等于约束值',
            style: TextStyle(fontSize: 11, color: Colors.grey)),
        const SizedBox(height: 6),
        Row(
          children: [
            // A1:紧密约束 + 无 factor
            Expanded(
              child: Container(
                height: 120,
                color: Colors.blue.shade100,
                child: const ColoredBox(
                  color: Colors.blue,
                  child: Center(child: Text('A1 tight+无factor')),
                ),
              ),
            ),
            const SizedBox(width: 8),
            // A2:紧密约束 + 有 factor
            Expanded(
              child: Container(
                height: 120,
                color: Colors.orange.shade100,
                child: ColoredBox(
                  color: Colors.orange.shade700,
                  child: const Center(
                    heightFactor: 1.5,
                    child: Text('A2 tight+有factor'),
                  ),
                ),
              ),
            ),
          ],
        ),
        const SizedBox(height: 4),
        const Text('A1 蓝色撑满120高(tight锁死+无factor→expand)',
            style: TextStyle(fontSize: 10, color: Colors.blue)),
        const Text('A2 橙色也撑满120高(但不是factor不生效,'
            '是橙色外层Container必须撑满父级)',
            style: TextStyle(fontSize: 10, color: Colors.orange)),
        const SizedBox(height: 10),

        // ── 宽松约束场景 ──
        const Text('场景 B:宽松约束(UnconstrainedBox 解除约束)',
            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12)),
        const Text('constraints 是 loose → Center 可以自由决定尺寸',
            style: TextStyle(fontSize: 11, color: Colors.grey)),
        const SizedBox(height: 6),
        Row(
          children: [
            // B1:宽松约束 + 无 factor
            Expanded(
              child: Container(
                height: 120,
                color: Colors.green.shade100,
                child: UnconstrainedBox(
                  child: ColoredBox(
                    color: Colors.green,
                    child: Center(
                      child: Container(width: 60, height: 30,
                          color: Colors.white),
                    ),
                  ),
                ),
              ),
            ),
            const SizedBox(width: 8),
            // B2:宽松约束 + 有 factor
            Expanded(
              child: Container(
                height: 120,
                color: Colors.purple.shade100,
                child: UnconstrainedBox(
                  child: ColoredBox(
                    color: Colors.purple,
                    child: Center(
                      widthFactor: 2,
                      heightFactor: 2,
                      child: Container(width: 60, height: 30,
                          color: Colors.white),
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
        const SizedBox(height: 4),
        const Text('B1 绿色=30高(宽松+无factor→child尺寸=30)',
            style: TextStyle(fontSize: 10, color: Colors.green)),
        const Text('B2 紫色=120×60(宽松+有factor→child×factor)',
            style: TextStyle(fontSize: 10, color: Colors.purple)),
      ],
    );
  }
}

// ────────────────────────────────────────────────────────────────
// ④ 知识点 4:widthFactor 详细行为
// ────────────────────────────────────────────────────────────────
class _Section4_WidthFactorDetail extends StatelessWidget {
  const _Section4_WidthFactorDetail();

  @override
  Widget build(BuildContext context) {
    return _Card(
      title: '④ widthFactor 详细行为',
      subtitle: 'Center 宽度 = child 宽度 × widthFactor',
      children: [
        const Text('前提:必须有宽松 width 约束才能看出效果\n'
            '(tight 约束下 Center 被锁死,factor 不影响实际渲染)',
            style: TextStyle(fontSize: 11)),
        const SizedBox(height: 8),
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _FactorDemo(label: 'factor=1', factor: 1),
            const SizedBox(width: 8),
            _FactorDemo(label: 'factor=2', factor: 2),
            const SizedBox(width: 8),
            _FactorDemo(label: 'factor=3', factor: 3),
          ],
        ),
      ],
    );
  }
}

class _FactorDemo extends StatelessWidget {
  final String label;
  final double factor;
  const _FactorDemo({required this.label, required this.factor});

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Column(
        children: [
          Container(
            height: 100,
            color: Colors.grey.shade200,
            child: UnconstrainedBox(
              child: ColoredBox(
                color: Colors.cyan.withValues(alpha: 0.6),
                child: Center(
                  widthFactor: factor,
                  child: Container(width: 30, height: 30,
                      color: Colors.cyan.shade900),
                ),
              ),
            ),
          ),
          const SizedBox(height: 4),
          Text('$label\nchild×$factor',
              textAlign: TextAlign.center,
              style: const TextStyle(fontSize: 10)),
        ],
      ),
    );
  }
}

// ────────────────────────────────────────────────────────────────
// ⑤ 知识点 5:heightFactor 详细行为
// ────────────────────────────────────────────────────────────────
class _Section5_HeightFactorDetail extends StatelessWidget {
  const _Section5_HeightFactorDetail();

  @override
  Widget build(BuildContext context) {
    return _Card(
      title: '⑤ heightFactor 详细行为',
      subtitle: 'Center 高度 = child 高度 × heightFactor',
      children: [
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _HeightDemo(label: '无 factor'),
            const SizedBox(width: 8),
            _HeightDemo(label: 'factor=2', factor: 2),
            const SizedBox(width: 8),
            _HeightDemo(label: 'factor=4', factor: 4),
          ],
        ),
        const SizedBox(height: 8),
        const Text('注意:无 factor 时 Center 撑满父级可用高度(expand),'
            '有 factor 时 shrink-wrap',
            style: TextStyle(fontSize: 11)),
      ],
    );
  }
}

class _HeightDemo extends StatelessWidget {
  final String label;
  final double? factor;
  const _HeightDemo({required this.label, this.factor});

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Column(
        children: [
          Container(
            height: 120,
            color: Colors.grey.shade200,
            child: factor != null
                ? UnconstrainedBox(
                    child: ColoredBox(
                      color: Colors.deepPurple.withValues(alpha: 0.6),
                      child: Center(
                        heightFactor: factor,
                        child: Container(width: 40, height: 25,
                            color: Colors.deepPurple.shade900),
                      ),
                    ),
                  )
                : ColoredBox(
                    color: Colors.deepPurple.shade300,
                    child: Center(
                      child: Container(width: 40, height: 25,
                          color: Colors.deepPurple.shade900),
                    ),
                  ),
          ),
          const SizedBox(height: 4),
          Text(label, style: const TextStyle(fontSize: 10)),
        ],
      ),
    );
  }
}

// ────────────────────────────────────────────────────────────────
// ⑥ 知识点 6:Row / Column 中的 Center
// ────────────────────────────────────────────────────────────────
class _Section6_InRowColumn extends StatelessWidget {
  const _Section6_InRowColumn();

  @override
  Widget build(BuildContext context) {
    return _Card(
      title: '⑥ Row / Column 中的 Center',
      subtitle: 'crossAxisAlignment 决定 Center 在交叉轴的约束类型',
      children: [
        const Text('Row 中主轴=水平,交叉轴=垂直:',
            style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold)),
        const SizedBox(height: 4),
        Row(
          crossAxisAlignment: CrossAxisAlignment.center, // 默认
          children: [
            Container(width: 60, height: 80, color: Colors.red),
            Center(
              heightFactor: 2,
              child: Container(width: 40, height: 30, color: Colors.blue),
            ),
            Container(width: 50, height: 60, color: Colors.green),
          ],
        ),
        const SizedBox(height: 4),
        const Text('默认 crossAxisAlignment.center → 交叉轴给宽松约束 → '
            'Center(heightFactor=2) = 30×2 = 60 高',
            style: TextStyle(fontSize: 11, color: Colors.blue)),
        const SizedBox(height: 10),
        const Text('Row 中 crossAxisAlignment.stretch:',
            style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold)),
        const SizedBox(height: 4),
        Row(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Container(width: 60, height: 80, color: Colors.red),
            Center(
              heightFactor: 2,
              child: Container(width: 40, height: 30, color: Colors.blue),
            ),
            Container(width: 50, height: 60, color: Colors.green),
          ],
        ),
        const SizedBox(height: 4),
        const Text('stretch → 交叉轴给 tight(80) 约束 → Center 高度被锁死在 80,'
            'heightFactor 在 tight 下无法让 Center 变小',
            style: TextStyle(fontSize: 11, color: Colors.blue)),
      ],
    );
  }
}

// ────────────────────────────────────────────────────────────────
// ⑦ 知识点 7:Center vs Align
// ────────────────────────────────────────────────────────────────
class _Section7_CenterVsAlign extends StatelessWidget {
  const _Section7_CenterVsAlign();

  @override
  Widget build(BuildContext context) {
    return _Card(
      title: '⑦ Center vs Align',
      subtitle: 'Center 是 Align 固定居中的简写',
      children: [
        const Text('两者唯一区别:alignment 是否固定',
            style: TextStyle(fontSize: 12)),
        const SizedBox(height: 8),
        Row(
          children: [
            Expanded(
              child: Container(
                height: 90,
                color: Colors.blue.shade50,
                child: const Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Text('Center',
                        style: TextStyle(fontSize: 11,
                            fontWeight: FontWeight.bold)),
                    Text('固定 Alignment.center',
                        style: TextStyle(fontSize: 10)),
                    Text('可设 widthFactor/heightFactor',
                        style: TextStyle(fontSize: 10)),
                  ],
                ),
              ),
            ),
            const SizedBox(width: 8),
            Expanded(
              child: Container(
                height: 90,
                color: Colors.orange.shade50,
                child: const Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Text('Align',
                        style: TextStyle(fontSize: 11,
                            fontWeight: FontWeight.bold)),
                    Text('可设任意 Alignment',
                        style: TextStyle(fontSize: 10)),
                    Text('可设 widthFactor/heightFactor',
                        style: TextStyle(fontSize: 10)),
                  ],
                ),
              ),
            ),
          ],
        ),
        const SizedBox(height: 8),
        const Text('选择建议:纯粹居中用 Center(语义清晰),'
            '需要其他对齐用 Align',
            style: TextStyle(fontSize: 11, fontStyle: FontStyle.italic)),
      ],
    );
  }
}

// ────────────────────────────────────────────────────────────────
// ⑧ 知识点 8:Center vs Container + alignment
// ────────────────────────────────────────────────────────────────
class _Section8_CenterVsContainer extends StatelessWidget {
  const _Section8_CenterVsContainer();

  @override
  Widget build(BuildContext context) {
    return _Card(
      title: '⑧ Center vs Container(alignment: center)',
      subtitle: '性能等价,但 Container 更灵活',
      children: [
        const Text('RenderObject 树相同,性能等价:',
            style: TextStyle(fontSize: 12)),
        const SizedBox(height: 4),
        Container(
          padding: const EdgeInsets.all(8),
          color: Colors.grey.shade100,
          child: const Text(
            'Center(child)       → RenderPositionedBox → child\n'
            'Container(          → RenderContainer\n'
            '  alignment: center, →   └─ RenderPositionedBox → child\n'
            '  child: ...)',
            style: TextStyle(fontSize: 11, fontFamily: 'monospace'),
          ),
        ),
        const SizedBox(height: 8),
        const Text('Container 额外支持:color / padding / margin / decoration / transform 等',
            style: TextStyle(fontSize: 11)),
        const SizedBox(height: 6),
        Row(
          children: [
            // 只有居中 → 用 Center
            Expanded(
              child: Container(
                height: 60,
                color: Colors.blue.shade50,
                child: const Center(child: Text('只有居中 → Center')),
              ),
            ),
            const SizedBox(width: 8),
            // 既要居中又要背景色 → Container
            Expanded(
              child: Container(
                height: 60,
                color: Colors.orange.shade100,
                alignment: Alignment.center,
                child: const Text('居中+背景 → Container'),
              ),
            ),
          ],
        ),
      ],
    );
  }
}

// ────────────────────────────────────────────────────────────────
// ⑨ 知识点 9:常见使用场景
// ────────────────────────────────────────────────────────────────
class _Section9_CommonUsage extends StatelessWidget {
  const _Section9_CommonUsage();

  @override
  Widget build(BuildContext context) {
    return _Card(
      title: '⑨ 常见使用场景',
      subtitle: '',
      children: [
        Row(
          children: [
            Expanded(
              child: _UsageBox(
                icon: Icons.sync,
                title: '加载指示器',
                code: 'const Center(child: CircularProgressIndicator())',
              ),
            ),
            const SizedBox(width: 8),
            Expanded(
              child: _UsageBox(
                icon: Icons.inbox,
                title: '空数据提示',
                code: 'const Center(child: Text("暂无数据"))',
              ),
            ),
          ],
        ),
        const SizedBox(height: 8),
        Row(
          children: [
            Expanded(
              child: _UsageBox(
                icon: Icons.check_circle,
                title: '成功提示',
                code: 'Center(child: Column(...))',
              ),
            ),
            const SizedBox(width: 8),
            Expanded(
              child: _UsageBox(
                icon: Icons.widgets,
                title: '居中卡片',
                code: 'Center(child: Card(...))',
              ),
            ),
          ],
        ),
      ],
    );
  }
}

class _UsageBox extends StatelessWidget {
  final IconData icon;
  final String title;
  final String code;
  const _UsageBox({required this.icon, required this.title, required this.code});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(8),
      decoration: BoxDecoration(
        color: Colors.grey.shade100,
        borderRadius: BorderRadius.circular(6),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Icon(icon, size: 14, color: Colors.blue),
              const SizedBox(width: 4),
              Text(title,
                  style: const TextStyle(
                      fontSize: 11, fontWeight: FontWeight.bold)),
            ],
          ),
          const SizedBox(height: 4),
          Text(code,
              style: const TextStyle(fontSize: 9, fontFamily: 'monospace')),
        ],
      ),
    );
  }
}

// ────────────────────────────────────────────────────────────────
// ⑩ 知识点 10:完整总结
// ────────────────────────────────────────────────────────────────
class _Section10_Summary extends StatelessWidget {
  const _Section10_Summary();

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: Colors.amber.shade100,
        borderRadius: BorderRadius.circular(8),
      ),
      child: const Text(
        '📌 Center 完整总结\n\n'
        '1. 本质:Align(alignment: center) 的简写\n'
        '2. 核心逻辑:shrinkWrap = factor != null || max 约束为∞\n'
        '   → 有 factor → shrink-wrap(尺寸 = child × factor)\n'
        '   → 无 factor → expand(尺寸 = 约束 max)\n'
        '3. widthFactor/heightFactor 生效前提:宽松约束\n'
        '4. Row/Column 中:crossAxisAlignment 决定约束类型\n'
        '   - center / start / end → 宽松约束\n'
        '   - stretch → tight 约束\n'
        '5. Center 没有 color/padding/margin → 需要装饰用 Container 包裹\n'
        '6. 选择建议:\n'
        '   - 纯粹居中 → Center\n'
        '   - 其他对齐 → Align\n'
        '   - 居中+装饰 → Container(alignment: center)',
        style: TextStyle(fontSize: 12),
      ),
    );
  }
}

// ────────────────────────────────────────────────────────────────
// 通用卡片组件
// ────────────────────────────────────────────────────────────────
class _Card extends StatelessWidget {
  final String title;
  final String subtitle;
  final List<Widget> children;
  const _Card({required this.title, this.subtitle = '', required this.children});

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.only(bottom: 16),
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(10),
        border: Border.all(color: Colors.grey.shade300),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withValues(alpha: 0.05),
            blurRadius: 6,
            offset: const Offset(0, 2),
          ),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(title,
              style: const TextStyle(
                  fontSize: 14, fontWeight: FontWeight.bold)),
          if (subtitle.isNotEmpty) ...[
            const SizedBox(height: 2),
            Text(subtitle,
                style: TextStyle(
                    fontSize: 11,
                    color: Colors.grey.shade600,
                    fontStyle: FontStyle.italic)),
          ],
          const SizedBox(height: 10),
          ...children,
        ],
      ),
    );
  }
}

Align

Center就是Align设置了居中。同样可以设置factor。

less 复制代码
import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(const MaterialApp(home: HomePage()));
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Align')),
      body: 
      Container(
        color: Colors.blue,
        child: Align(
          alignment: Alignment.bottomRight,
          child: Container(
            width: 100,
            height: 100,
            color: Colors.green,
          ),
        ),
      )
    );
  }
}
相关推荐
小p1 小时前
nextjs学习9: Next.js 渲染与缓存
前端·后端
乘风gg1 小时前
AI 时代,你的编程能力在第几层?我敢说,大多数人卡在第一层
前端·ai编程·claude
东风破_1 小时前
React Router v7 实战:用路由配置、懒加载与嵌套路由搭建一个完整的 SPA
前端
引山洪081 小时前
Babylon.js 8.x 中文文档整理——Node篇 (上)
前端·webgl
柒和远方1 小时前
V058:前端路由的第一性原理:从 hashchange 手写路由,到 React Router 的嵌套与懒加载
前端·javascript·react.js
计算机魔术师1 小时前
阿里云上线 One Key MCP 服务:兼容 Qoder、Codex 等,可一键调用多家 MCP 服务
前端
Darling噜啦啦1 小时前
React Router 全家桶实战:从路由懒加载到嵌套路由的 6 大核心玩法
前端·react.js
Goodbye1 小时前
组件详解:从起源到未来的全方位解读
前端
无糖可可果1 小时前
从前端路由的起源到 React Router 实战
前端