flutter系列之:永遠不用擔心組件溢出的Wrap

簡介

我們在flutter中使用能夠包含多個child的widget的時候,經常會遇到超出邊界範圍的情況,尤其是在Column和Row的情況下,那麼我們有沒有什麼好的解決辦法呢?答案就是今天我們要講解的Wrap。

Row和Column的困境

Row和Column中可以包含多個子widget,如果子widget超出了Row或者Column的範圍會出現什麼情況呢?

我們以Row的情況舉個例子:

  Widget build(BuildContext context) {
    return Row(
      textDirection: TextDirection.ltr,
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        YellowBox(),
        YellowBox(),
        Expanded(
          child: YellowBox(),
        ),
        YellowBox(),
      ],
    );
  }

上面的例子中,我們在Row中添加了幾個YellowBox,YellowBox是一個width=100,height=50的長方形:

  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.yellow,
        border: Border.all(),
      ),
    );
  }

運行上面的程式碼,我們可以得到這樣的介面:

如果在Row中多添加幾個YellowBox會有什麼效果呢?

我們在上面的Row中多添加一個yellowBox:

  Widget build(BuildContext context) {
    return Row(
      textDirection: TextDirection.ltr,
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        YellowBox(),
        YellowBox(),
        Expanded(
          child: YellowBox(),
        ),
        YellowBox(),
        YellowBox(),
      ],
    );
  }

運行可以得到下面的介面:

可以看到,因為Row中的子widget太多了,已經超出了Row的範圍,介面上已經報錯了。

要解決這個問題,就需要使用到Wrap組件。

Wrap組件詳解

先來看下Wrap的定義:

class Wrap extends MultiChildRenderObjectWidget

Wrap繼承自MultiChildRenderObjectWidget,表示可以包含多個子child。

接下來是Wrap的構造函數:

  Wrap({
    Key? key,
    this.direction = Axis.horizontal,
    this.alignment = WrapAlignment.start,
    this.spacing = 0.0,
    this.runAlignment = WrapAlignment.start,
    this.runSpacing = 0.0,
    this.crossAxisAlignment = WrapCrossAlignment.start,
    this.textDirection,
    this.verticalDirection = VerticalDirection.down,
    this.clipBehavior = Clip.none,
    List<Widget> children = const <Widget>[],
  }) : assert(clipBehavior != null), super(key: key, children: children);

構造函數中列出了Wrap中常用的屬性。

其中direction表示子組件的排列方向。alignment表示的是子組件的對其方式。spacing表示子組件的間隔。

跟spacing類似的還有一個runSpacing屬性,兩者有什麼區別呢? 我們還是通過一個具體的例子來查看。

  Widget build(BuildContext context) {
    return Wrap(
      direction: Axis.horizontal,
      textDirection: TextDirection.ltr,
      children: [
        YellowBox(),
        YellowBox(),
        // Expanded(
        //   child: YellowBox(),
        // ),
        YellowBox(),
        YellowBox(),
        YellowBox(),
      ],
    );

還是上面的例子,這裡我們使用Wrap來替換Row,這裡我們使用了direction選項,表示是在橫向方向進行Wrap。

然後在children中添加了5個YellowBox。

注意,這裡不能使用Expanded,否則會報錯,所以我們把Expanded注釋掉了,運行可以得到下面的介面:

可以看到YellowBox是按行的方向來排列的,超出一行的範圍之後就會自動換行,這也就是Wrap的功能。

我們在講解Wrap的時候,還提到了兩個屬性,分別是spacing和runSpacing。兩者有什麼區別呢?

先看下spacing:

  Widget build(BuildContext context) {
    return Wrap(
      direction: Axis.horizontal,
      spacing: 10,
      textDirection: TextDirection.ltr,
      children: [
        YellowBox(),
        YellowBox(),
        // Expanded(
        //   child: YellowBox(),
        // ),
        YellowBox(),
        YellowBox(),
        YellowBox(),
      ],
    );
  }

我們先給Wrap添加spacing屬性,運行可以得到下面的介面:

可以看到YellowBox之間是用spacing來進行分割的。

那麼如果我們希望在Wrap換行的時候,兩行之間也有一些間距應該怎麼處理呢?

這個時候就需要用到runSpacing屬性了:

  Widget build(BuildContext context) {
    return Wrap(
      direction: Axis.horizontal,
      spacing: 10,
      runSpacing: 10,
      textDirection: TextDirection.ltr,
      children: [
        YellowBox(),
        YellowBox(),
        // Expanded(
        //   child: YellowBox(),
        // ),
        YellowBox(),
        YellowBox(),
        YellowBox(),
      ],
    );
  }

運行可以得到下面的介面:

Wrap已經完美的運行了。

總結

Wrap可以通過使用不同的direction來替換Row或者Column,我們在組件可能會超出範圍的時候,就可以考慮使用Wrap了。

本文的例子://github.com/ddean2009/learn-flutter.git

更多內容請參考 www.flydean.com

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!