likes
comments
collection
share

Flutter之Flexible与Expanded

作者站长头像
站长
· 阅读数 5

在 Flutter 中,FlexibleExpanded 小部件都用于在 Flex(如 RowColumn)布局中控制子小部件的布局。尽管它们看起来很相似,但存在一些关键的区别:

Flexible

  • Flexible 小部件允许其子小部件在主轴方向上根据可用空间来伸缩。使用 Flexible 时,可以指定子小部件的 flex 因子来决定其在 Flex 容器中占据的空间比例。
  • Flexible 还允许子小部件保持其固有尺寸。通过设置 fit 属性为 FlexFit.loose(默认值),子小部件可以在不超过分配空间的情况下保持其原始大小。也就是说,如果子小部件的内容不足以填满其分配的空间,它可以比分配的空间更小。大家可能对属性为 FlexFit.loose好奇,这个尽可能填充其空间是什么意思呢?假如有个需求,需要后一个Widget紧跟前一个Widget,但前一个Widget长度不是固定的,可能会溢出屏幕,这样的需求该如何实现呢?有的开发同学可能想到会计算前一个Widget的长度,用屏幕的宽减去对应的长度剩余的就是该Widget的宽度,这样可以解决问题,但其实Flutter中大多地方是不用计算的,使用FlexFit.loose则可以完美解决问题。代码如下:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Drag to Sort',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<String> _items = List<String>.generate(10, (i) => 'Item $i');
  bool _isReorderable = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
    //  backgroundColor: Colors.blueAccent,
      appBar: AppBar(
        title: Text('Test'),
      ),
      body: Column(children: [
        _buildContainer(Colors.lightBlue,const Flexible(
            child: Text("这是一个项目",maxLines: 1,overflow: TextOverflow.ellipsis,))),
        _buildContainer(Colors.red, const Flexible(
            fit: FlexFit.tight,
            child: Text("这是一个项目",maxLines: 1,overflow: TextOverflow.ellipsis,))),
        _buildContainer(Colors.purple,  Flexible(
            fit: FlexFit.tight,
            child: Text("这是一个项目" * 6,maxLines: 1,overflow: TextOverflow.ellipsis,))),
        _buildContainer(Colors.blue,  Expanded(
            child: Text("这是一个项目" * 6,maxLines: 1,overflow: TextOverflow.ellipsis,))),

      ],),
    );
  }

  Container _buildContainer(Color color,Widget child) {
    return Container(
      height: 56,
      color: color,
      child: Row(
        children: [
          const SizedBox(width:16),
          const Text("来源:"),
          child,
          const SizedBox(width: 8),
          Container(
            padding: EdgeInsets.all(5),
            decoration: const BoxDecoration(
                color: Colors.cyan,
                borderRadius: BorderRadius.all(Radius.circular(6))
            ),
            child: Text("项目"),
          ),
          const SizedBox(width:16),
        ],
      ),
    );
  }
}

效果分别如下:

Flutter之Flexible与Expanded

Expanded

  • Expanded 小部件是 Flexible 小部件的一个特殊情况,继承Flexible,其 fit 属性默认设置为 FlexFit.tight。这意味着 Expanded 小部件会强制其子小部件填满在 Flex 容器中分配给它的空间。
  • 使用 Expanded 时,子小部件不能保持其固有大小,而是被拉伸以占据所有可用空间(根据其 flex 因子)。

示例代码

Row(
  children: <Widget>[
    Flexible(
      flex: 2,
      child: Container(
        color: Colors.blue,
        height: 100,
      ),
    ),
    Flexible(
      flex: 1,
      fit: FlexFit.tight,
      child: Container(
        color: Colors.red,
        height: 100,
      ),
    ),
    Expanded(
      flex: 1,
      child: Container(
        color: Colors.green,
        height: 100,
      ),
    ),
  ],
)

效果如图所示:

Flutter之Flexible与Expanded

  • 第一个 Container 使用 Flexible,并且其 flex 值为 2,这意味着它会尝试占据两倍于其他子元素分配的空间。由于 fit 属性为默认值 FlexFit.loose,如果容器内容不足以填满其分配的空间,它可以比分配的空间更小。
  • 第二个 Container 也使用 Flexible,但其 fit 设置为 FlexFit.tight,使其行为类似于 Expanded
  • 第三个 Container 使用 Expanded,自动应用 FlexFit.tight,确保填满分配的空间。

总的来说,Expanded 是特定于要求子小部件填满所有可用空间的场景的 Flexible。当你需要子小部件根据其大小灵活调整时,应该使用 Flexible