一統天下 flutter - widget 佈局類(可以有多個子): CustomMultiChildLayout - 自定義多組件佈局

源碼 https://github.com/webabcd/flutter_demo
作者 webabcd

一統天下 flutter - widget 佈局類(可以有多個子): CustomMultiChildLayout - 自定義多組件佈局

示例如下:

lib\widget\layout\custom_multi_child_layout.dart

/*
 * CustomMultiChildLayout - 自定義多組件佈局
 *
 * 注:約束是從上向下傳遞的,尺寸是從下向上傳遞的
 */

import 'package:flutter/material.dart';
import 'package:flutter_demo/helper.dart';

class CustomMultiChildLayoutDemo extends StatefulWidget {
  const CustomMultiChildLayoutDemo({Key? key}) : super(key: key);

  @override
  _CustomMultiChildLayoutDemoState createState() => _CustomMultiChildLayoutDemoState();
}

class _CustomMultiChildLayoutDemoState extends State<CustomMultiChildLayoutDemo> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("title"),),
      backgroundColor: Colors.orange,
      /// 自定義佈局
      body: CustomMultiChildLayout(
        /// 通過指定的 delegate 實現具體的佈局
        delegate: _MyMultiChildLayoutDelegate(),
        children: [
          /// 通過 LayoutId 指定需要佈局的組件的 id
          LayoutId(
            id: 'a',
            child: Container(
              color: Colors.red,
            ),
          ),
          LayoutId(
            id: 'b',
            child: Container(
              width: 200,
              height: 200,
              color: Colors.green,
            ),
          ),
        ],
      ),
    );
  }
}

class _MyMultiChildLayoutDelegate extends MultiChildLayoutDelegate {

  /// 用於對每個子組件做佈局
  @override
  void performLayout(Size size) {
    /// 這個 size 就是 CustomMultiChildLayout 的可用空間
    log("performLayout size:$size");

    /// 用於判斷 CustomMultiChildLayout 的 children 內是否存在指定 id 的組件
    /// 在 CustomMultiChildLayout 的 children 內需要通過 LayoutId 指定組件的 id
    if (hasChild('a')) {

    }

    /// 對 id 爲 a 的組件佈局,父把約束告訴子,然後子會把自己的尺寸告訴父
    var size_a = layoutChild("a", BoxConstraints(minWidth: 100, minHeight: 100, maxWidth: 100, maxHeight: 100));
    /// 對 id 爲 b 的組件佈局,父把約束告訴子,然後子會把自己的尺寸告訴父
    var size_b = layoutChild("b", BoxConstraints(minWidth: 0, minHeight: 0, maxWidth: 100, maxHeight: size.height));

    /// 設置 id 爲 a 的組件的位置
    positionChild("a", Offset(0, 0));
    /// 設置 id 爲 b 的組件的位置
    positionChild("b", Offset(100, 100));
  }

  /// 當 MultiChildLayoutDelegate 發生變化時,通過這裏決定是否需要重新佈局
  @override
  bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) {
    return true;
  }

  /// constraints 爲 CustomMultiChildLayout 的父傳給 CustomMultiChildLayout 的約束
  /// 返回值爲 CustomMultiChildLayout 根據約束決定的自己的尺寸
  @override
  Size getSize(BoxConstraints constraints) {
    var size = super.getSize(constraints);
    log('getSize constraints:$constraints, size:$size');
    return size;
  }

  /// constraints 爲 CustomMultiChildLayout 傳給 id 爲 childId 的子的約束
  /// 返回值爲子根據約束決定的自己的尺寸
  @override
  Size layoutChild(Object childId, BoxConstraints constraints) {
    var size = super.layoutChild(childId, constraints);
    log('layoutChild childId:$childId, constraints:$constraints, size:$size');
    return size;
  }
}

源碼 https://github.com/webabcd/flutter_demo
作者 webabcd

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章