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做响应式布局

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

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

相关推荐
雨季6666 小时前
Flutter 三端应用实战:OpenHarmony 简易“动态主题切换卡片”交互模式
flutter·ui·交互·dart
熊猫钓鱼>_>6 小时前
【开源鸿蒙跨平台开发先锋训练营】Day 19: 开源鸿蒙React Native动效体系构建与混合开发复盘
react native·华为·开源·harmonyos·鸿蒙·openharmony
打小就很皮...6 小时前
《在 React/Vue 项目中引入 Supademo 实现交互式新手指引》
前端·supademo·新手指引
C澒6 小时前
系统初始化成功率下降排查实践
前端·安全·运维开发
摘星编程6 小时前
React Native + OpenHarmony:自定义useFormik表单处理
javascript·react native·react.js
向哆哆6 小时前
构建健康档案管理快速入口:Flutter × OpenHarmony 跨端开发实战
flutter·开源·鸿蒙·openharmony·开源鸿蒙
2601_949593656 小时前
基础入门 React Native 鸿蒙跨平台开发:BackHandler 返回键控制
react native·react.js·harmonyos
C澒6 小时前
面单打印服务的监控检查事项
前端·后端·安全·运维开发·交通物流
mocoding7 小时前
使用Flutter强大的图标库fl_chart优化鸿蒙版天气预报温度、降水量、湿度展示
flutter·华为·harmonyos
pas1367 小时前
39-mini-vue 实现解析 text 功能
前端·javascript·vue.js