Flutter for OpenHarmony 实战:AspectRatio/Center/Wrap等布局组件实用技巧

Flutter for OpenHarmony 实战:AspectRatio/Center/Wrap等布局组件实用技巧

文章目录

  • [Flutter for OpenHarmony 实战:AspectRatio/Center/Wrap等布局组件实用技巧](#Flutter for OpenHarmony 实战:AspectRatio/Center/Wrap等布局组件实用技巧)
    • 摘要
    • 前言
    • 一、AspectRatio宽高比
      • [1.1 基础用法](#1.1 基础用法)
      • [1.2 图片保持宽高比](#1.2 图片保持宽高比)
      • [1.3 卡片宽高比](#1.3 卡片宽高比)
    • 二、Center居中
      • [2.1 基础Center](#2.1 基础Center)
      • [2.2 Center vs Align](#2.2 Center vs Align)
      • [2.3 Center widthFactor和heightFactor](#2.3 Center widthFactor和heightFactor)
    • 三、Wrap自动换行
      • [3.1 基础Wrap](#3.1 基础Wrap)
      • [3.2 Wrap方向和对齐](#3.2 Wrap方向和对齐)
      • [3.3 Wrap间距](#3.3 Wrap间距)
      • [3.4 标签云](#3.4 标签云)
    • 四、其他布局组件
      • [4.1 SafeArea安全区域](#4.1 SafeArea安全区域)
      • [4.2 Expanded和Flexible](#4.2 Expanded和Flexible)
      • [4.3 Overflow溢出处理](#4.3 Overflow溢出处理)
      • [4.4 IndexedStack](#4.4 IndexedStack)
      • [4.5 Transform变换](#4.5 Transform变换)
      • [4.6 LayoutBuilder响应式布局](#4.6 LayoutBuilder响应式布局)
    • 总结

摘要

Flutter提供了多种布局组件,AspectRatio设置宽高比,Center居中对齐,Wrap自动换行。这些组件在特定场景下非常有用。这篇文章我想讲解这些布局组件的使用方法和实用技巧。

前言

除了常用的Row、Column、Stack,Flutter还有很多布局组件。AspectRatio可以保持宽高比,Center很常用,Wrap能自动换行。

这些组件用好了,很多布局问题都能轻松解决。这篇文章我想分享这些布局组件的使用经验。

一、AspectRatio宽高比

1.1 基础用法

dart 复制代码
class BasicAspectRatio extends StatelessWidget {
  const BasicAspectRatio({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 1:1正方形
        AspectRatio(
          aspectRatio: 1.0,
          child: Container(
            color: Colors.blue,
            child: Center(
              child: Text('1:1'),
            ),
          ),
        ),

        // 16:9宽屏
        AspectRatio(
          aspectRatio: 16 / 9,
          child: Container(
            color: Colors.green,
            child: Center(
              child: Text('16:9'),
            ),
          ),
        ),

        // 4:3传统比例
        AspectRatio(
          aspectRatio: 4 / 3,
          child: Container(
            color: Colors.orange,
            child: Center(
              child: Text('4:3'),
            ),
          ),
        ),
      ],
    );
  }
}

1.2 图片保持宽高比

dart 复制代码
class ImageAspectRatio extends StatelessWidget {
  const ImageAspectRatio({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 使用AspectRatio保持图片比例
        AspectRatio(
          aspectRatio: 16 / 9,
          child: Image.network(
            'https://flutter.dev/images/flutter-logo-sharing.png',
            fit: BoxFit.cover,
          ),
        ),
      ],
    );
  }
}

1.3 卡片宽高比

dart 复制代码
class CardAspectRatio extends StatelessWidget {
  const CardAspectRatio({super.key});

  @override
  Widget build(BuildContext context) {
    return GridView.count(
      crossAxisCount: 2,
      children: List.generate(10, (index) {
        return Card(
          child: Column(
            children: [
              // 图片保持16:9
              AspectRatio(
                aspectRatio: 16 / 9,
                child: Container(
                  decoration: BoxDecoration(
                    color: Colors.primaries[index % Colors.primaries.length],
                    borderRadius: BorderRadius.vertical(
                      top: Radius.circular(12),
                    ),
                  ),
                ),
              ),
              // 内容
              Padding(
                padding: EdgeInsets.all(8),
                child: Text('卡片 $index'),
              ),
            ],
          ),
        );
      }),
    );
  }
}

二、Center居中

2.1 基础Center

dart 复制代码
class BasicCenter extends StatelessWidget {
  const BasicCenter({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Colors.blue,
        width: 100,
        height: 100,
      ),
    );
  }
}

2.2 Center vs Align

dart 复制代码
class CenterVsAlign extends StatelessWidget {
  const CenterVsAlign({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // Center居中
        Container(
          height: 200,
          color: Colors.grey,
          child: Center(
            child: Container(
              color: Colors.blue,
              width: 100,
              height: 100,
            ),
          ),
        ),

        // Align居中
        Container(
          height: 200,
          color: Colors.grey,
          child: Align(
            alignment: Alignment.center,
            child: Container(
              color: Colors.green,
              width: 100,
              height: 100,
            ),
          ),
        ),

        // Align自定义位置
        Container(
          height: 200,
          color: Colors.grey,
          child: Align(
            alignment: Alignment(0.5, -0.5),
            child: Container(
              color: Colors.orange,
              width: 100,
              height: 100,
            ),
          ),
        ),
      ],
    );
  }
}

2.3 Center widthFactor和heightFactor

dart 复制代码
class CenterFactors extends StatelessWidget {
  const CenterFactors({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 默认Center
        Container(
          height: 150,
          color: Colors.grey,
          child: Center(
            child: Container(color: Colors.blue, width: 50, height: 50),
          ),
        ),

        // 设置widthFactor和heightFactor
        Container(
          height: 150,
          color: Colors.grey,
          child: Center(
            widthFactor: 2,
            heightFactor: 2,
            child: Container(color: Colors.green, width: 50, height: 50),
          ),
        ),
      ],
    );
  }
}

三、Wrap自动换行

3.1 基础Wrap

dart 复制代码
class BasicWrap extends StatelessWidget {
  const BasicWrap({super.key});

  @override
  Widget build(BuildContext context) {
    return Wrap(
      children: List.generate(20, (index) {
        return Container(
          margin: EdgeInsets.all(4),
          padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
          decoration: BoxDecoration(
            color: Colors.blue,
            borderRadius: BorderRadius.circular(20),
          ),
          child: Text(
            '标签 $index',
            style: TextStyle(color: Colors.white),
          ),
        );
      }),
    );
  }
}

3.2 Wrap方向和对齐

dart 复制代码
class WrapAlignment extends StatelessWidget {
  const WrapAlignment({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 水平排列,自动换行
        Wrap(
          direction: Axis.horizontal,
          alignment: WrapAlignment.start,
          children: _chips(),
        ),

        // 水平居中
        Wrap(
          alignment: WrapAlignment.center,
          children: _chips(),
        ),

        // 水平两端对齐
        Wrap(
          alignment: WrapAlignment.spaceBetween,
          children: _chips(),
        ),

        // 垂直排列
        Wrap(
          direction: Axis.vertical,
          children: _chips(),
        ),
      ],
    );
  }

  List<Widget> _chips() {
    return List.generate(10, (index) {
      return Chip(label: Text('标签 $index'));
    });
  }
}

3.3 Wrap间距

dart 复制代码
class WrapSpacing extends StatelessWidget {
  const WrapSpacing({super.key});

  @override
  Widget build(BuildContext context) {
    return Wrap(
      spacing: 8, // 主轴间距
      runSpacing: 8, // 交叉轴间距
      children: List.generate(20, (index) {
        return Container(
          width: 80,
          height: 80,
          decoration: BoxDecoration(
            color: Colors.primaries[index % Colors.primaries.length],
            borderRadius: BorderRadius.circular(8),
          ),
          child: Center(
            child: Text(
              '$index',
              style: TextStyle(color: Colors.white),
            ),
          ),
        );
      }),
    );
  }
}

3.4 标签云

dart 复制代码
class TagCloud extends StatelessWidget {
  const TagCloud({super.key});

  final List<String> tags = const [
    'Flutter', 'Dart', 'OpenHarmony', '移动开发', '跨平台',
    'UI设计', '性能优化', '状态管理', '动画', '网络请求',
  ];

  @override
  Widget build(BuildContext context) {
    return Wrap(
      spacing: 8,
      runSpacing: 8,
      children: tags.map((tag) {
        return Chip(
          label: Text(tag),
          onDeleted: () {},
          backgroundColor: Colors.blue.shade100,
        );
      }).toList(),
    );
  }
}

四、其他布局组件

4.1 SafeArea安全区域

dart 复制代码
class SafeAreaDemo extends StatelessWidget {
  const SafeAreaDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Container(
        color: Colors.blue,
        child: Center(
          child: Text('内容避开安全区域'),
        ),
      ),
    );
  }
}

4.2 Expanded和Flexible

dart 复制代码
class ExpandedFlexible extends StatelessWidget {
  const ExpandedFlexible({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // Expanded占满剩余空间
        Expanded(
          flex: 1,
          child: Container(color: Colors.red),
        ),
        Expanded(
          flex: 2,
          child: Container(color: Colors.green),
        ),

        // Flexible根据子Widget大小
        Flexible(
          flex: 1,
          child: Container(
            color: Colors.blue,
            width: 100,
          ),
        ),
      ],
    );
  }
}

4.3 Overflow溢出处理

dart 复制代码
class OverflowHandling extends StatelessWidget {
  const OverflowHandling({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // OverflowBox允许子Widget溢出
        Container(
          height: 100,
          color: Colors.grey,
          child: OverflowBox(
            maxHeight: 150,
            child: Container(
              height: 150,
              color: Colors.red,
            ),
          ),
        ),

        // SizedOverflowBox
        Container(
          color: Colors.grey,
          child: SizedOverflowBox(
            size: Size(100, 100),
            child: Container(
              width: 150,
              height: 150,
              color: Colors.blue,
            ),
          ),
        ),
      ],
    );
  }
}

4.4 IndexedStack

dart 复制代码
class IndexedStackDemo extends StatefulWidget {
  const IndexedStackDemo({super.key});

  @override
  State<IndexedStackDemo> createState() => _IndexedStackDemoState();
}

class _IndexedStackDemoState extends State<IndexedStackDemo> {
  int _index = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(
          height: 200,
          child: IndexedStack(
            index: _index,
            children: [
              Container(color: Colors.red, child: Center(child: Text('页面1'))),
              Container(color: Colors.green, child: Center(child: Text('页面2'))),
              Container(color: Colors.blue, child: Center(child: Text('页面3'))),
            ],
          ),
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            ElevatedButton(
              onPressed: () => setState(() => _index = 0),
              child: Text('1'),
            ),
            ElevatedButton(
              onPressed: () => setState(() => _index = 1),
              child: Text('2'),
            ),
            ElevatedButton(
              onPressed: () => setState(() => _index = 2),
              child: Text('3'),
            ),
          ],
        ),
      ],
    );
  }
}

4.5 Transform变换

dart 复制代码
class TransformDemo extends StatelessWidget {
  const TransformDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: [
        // 旋转
        Transform.rotate(
          angle: 0.5,
          child: Container(color: Colors.red, width: 80, height: 80),
        ),

        // 缩放
        Transform.scale(
          scale: 1.5,
          child: Container(color: Colors.green, width: 50, height: 50),
        ),

        // 平移
        Transform.translate(
          offset: Offset(20, 20),
          child: Container(color: Colors.blue, width: 60, height: 60),
        ),
      ],
    );
  }
}

4.6 LayoutBuilder响应式布局

dart 复制代码
class LayoutBuilderDemo extends StatelessWidget {
  const LayoutBuilderDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        if (constraints.maxWidth > 600) {
          return _buildWideLayout();
        } else {
          return _buildNarrowLayout();
        }
      },
    );
  }

  Widget _buildWideLayout() {
    return Row(
      children: [
        Expanded(child: Container(color: Colors.red, height: 100)),
        Expanded(child: Container(color: Colors.green, height: 100)),
      ],
    );
  }

  Widget _buildNarrowLayout() {
    return Column(
      children: [
        Container(color: Colors.red, height: 100),
        Container(color: Colors.green, height: 100),
      ],
    );
  }
}

总结

各种布局组件都有其适用场景。

核心要点

  1. AspectRatio保持宽高比
  2. Center快速居中
  3. Wrap自动换行
  4. SafeArea避开安全区域
  5. LayoutBuilder响应式布局

最佳实践

  • 图片用AspectRatio保持比例
  • Center比Align.center更简洁
  • Wrap用于标签等自动换行场景
  • SafeArea保护重要内容
  • LayoutBuilder做响应式布局

合理选择布局组件让开发更高效。

欢迎加入开源鸿蒙跨平台社区:开源鸿蒙跨平台开发者社区

相关推荐
早點睡39022 分钟前
Harmony Flutter 跨平台开发实战:鸿蒙与音乐律动艺术、贝塞尔流体律动:三阶贝塞尔曲线的“呼吸“感
flutter
2501_9219308325 分钟前
进阶实战 Flutter for OpenHarmony:响应式状态机系统 - 复杂状态流转实现
flutter
a1117761 小时前
星球主题个人主页(纯HTML 开源)
前端·html
星空22231 小时前
【HarmonyOS】day44:RN_of_HarmonyOS实战项目_富文本编辑器
华为·harmonyos
松叶似针1 小时前
Flutter三方库适配OpenHarmony【doc_text】— Word 文档格式深度科普:从 OLE2 到 OOXML
flutter·harmonyos
旭日跑马踏云飞1 小时前
【Nginx】相关优化
运维·javascript·nginx
木斯佳1 小时前
HarmonyOS实战(解决方案篇)—从实战案例了解应用并发设计
华为·harmonyos
空条jo太郎1 小时前
echarts图表联动
前端
webkubor1 小时前
2026 年 把网页交互的主控权拿回前端手中 🚀
前端·javascript·人工智能
空白诗1 小时前
Harmony Flutter 跨平台开发实战:鸿蒙与音乐律动艺术、粒子系统与流体模拟:动态粒子的视觉盛宴
flutter·harmonyos