Flex in Flutter

266 阅读1分钟

注意点

  1. FlexItem 需要父组件有是FlexList
  2. FlexItem 界面边界 一般是 关于机型的函数: 比如 * MediaQuery.of(context).size.height < 640 ? 220 : 240
  3. 对于需要变形的FlexItem,对应的 flexFlag 记得设置为true
  4. FlexItem flexFlag 为 ture时, children不能有Spacer()

说明

场景:

  1. 如果List界面边界比估计的内容最小边界大,则是正常的ListView列表。
  2. 如果List界面边界比估计的内容最小边界小,
  • 对于Item 没有flexFlag为true, 同1。
  • 对于Item flexFlag为true, 不去管开发者的设置,取最小值。[即尽量让内容塞到当前屏里]

对于item元素,布局的关注的是单个对象的占页面的尺寸

对于List列表,布局的关注的是全局的信息

可能会有Bug...

代码

  • FlexList
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class FlexList extends StatelessWidget {
  const FlexList(
      {Key key,
      @required this.minHigh,
      this.maxHigh = double.infinity,
      this.appBar,
      this.backgroundColor,
      this.children,
      this.isCoverContent})
      : super(key: key);
  final double minHigh;
  final double maxHigh;
  final PreferredSizeWidget appBar;
  final Color backgroundColor;
  final List<Widget> children;
  final bool isCoverContent;

  @override
  Widget build(BuildContext context) {
    double contextHight = MediaQuery.of(context).size.height -
        MediaQuery.of(context).viewPadding.top -
        (appBar != null ? 0 : kToolbarHeight);
    debugPrint(contextHight.toString());
    return ListView(children: <Widget>[
      Container(
          height: min(max(contextHight, minHigh ?? 0), maxHigh) +
              MediaQuery.of(context).viewInsets.bottom,
          child: Scaffold(
            appBar: appBar,
            backgroundColor: backgroundColor ?? Colors.transparent,
            body: ChangeNotifierProvider<FlexParent>(
                builder: (context) =>
                    FlexParent(isCoverContent: isCoverContent == null ? contextHight > minHigh : isCoverContent),
                child: GestureDetector(
                  behavior: HitTestBehavior.translucent,
                  onTap: () {
                    FocusScope.of(context).requestFocus(FocusNode());
                  },
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children: children,
                  ),
                )),
          ))
    ]);
  }
}

class FlexParent with ChangeNotifier {
  bool isCoverContent;
  FlexParent({this.isCoverContent});
}

  • FlexItem
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import 'flex_list.dart';

class FlexItem extends StatelessWidget {
  const FlexItem({
    Key key,
    @required this.windowHigh,
    this.padding,
    this.children,
    this.flexFlag = false,
    this.crossAxisAlignment = CrossAxisAlignment.center,
    this.textDirection,
    this.verticalDirection = VerticalDirection.down,
    this.textBaseline,
  }) : super(key: key);
  final double windowHigh;
  final EdgeInsets padding;
  final List<Widget> children;
  final bool flexFlag;

  final CrossAxisAlignment crossAxisAlignment;
  final TextDirection textDirection;
  final VerticalDirection verticalDirection;
  final TextBaseline textBaseline;

  @override
  Widget build(BuildContext context) {
    return Consumer<FlexParent>(
      builder: (_, model, __) {
        bool minFlag = false;
        if (model.isCoverContent == false) minFlag = flexFlag;
        debugPrint('FlexItem:' +
            windowHigh.toString() +
            ' ' +
            minFlag.toString());
        return Container(
          height: minFlag ? null : windowHigh,
          padding: padding ?? EdgeInsets.all(0),
          width: MediaQuery.of(context).size.width,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: children,
            // options
            crossAxisAlignment: crossAxisAlignment,
            textDirection: textDirection,
            verticalDirection: verticalDirection,
            textBaseline: textBaseline,
          ),
        );
      },
      // )
    );
  }
}