首页 > 解决方案 > 调整父小部件的大小以适应 Flutter 中的子帖子“变换”

问题描述

Transforms在 Flutter 中使用来创建一个滚动轮播,以便从各种选项中进行选择。

这使用了标准元素,例如ListView.builder,除了 Transform 的父小部件不会按比例缩小以适应此处所示的内容之外,这些元素都可以正常工作:

注意透视变换周围的间隙 这是用于生成“卡片”的代码(实际上有一张卡片,但我已将其剥离以尝试使所有内容正确缩放):

    return Align(
      child: Transform(
        alignment: Alignment.center,
        transform: mat,
        child: Container(
          height: 220,
          color: color,
          width: MediaQuery.of(context).size.width * 0.7,
          child: Text(
            offset.toString(),
            style: TextStyle(color: Colors.white, fontSize: 12.0),
          ),
        ),
      ),
    );
  }

即使我删除了容器的“高度”参数(因此所有内容都会缩放以适合“文本”小部件),包含Transform小部件的框周围仍然有间隙。

Flutter 似乎没有任何文档来显示如果其中的对象被转换,如何重新缩放父级 - 这里的任何人都知道或有任何解决方法的想法吗?

编辑:从此返回的build小部件在有状态小部件的小部件中使用。堆栈是 Column > Container > ListView.builder。

如果我删除变换,容器会按照我的意愿组合在一起 - 似乎在容器上执行透视变换会“缩小”它的内容(在这种情况下,颜色 - 检查链接的屏幕抓取),但没有重新缩放容器本身,这是我想要实现的。

标签: flutterflutter-layoutflutter-animation

解决方案


我对此有一个棘手的解决方案:addPostFrameCallback + 覆盖。

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

// ignore: must_be_immutable
class ChildSizeWidget extends HookWidget {
  final Widget Function(BuildContext context, Widget child, Size size) builder;
  final Widget child;
  final GlobalKey _key = GlobalKey();
  OverlayEntry _overlay;

  ChildSizeWidget({ this.child, this.builder });

  @override
  Widget build(BuildContext context) {
    final size = useState<Size>(null);

    useEffect(() {
      WidgetsBinding.instance.addPostFrameCallback((timestamp) {
        _overlay = OverlayEntry(
          builder: (context) => Opacity(
            child: SingleChildScrollView(
              child: Container(
                child: child,
                key: _key,
              ),
            ),
            opacity: 0.0,
          ),
        );

        Overlay.of(context).insert(_overlay);

        WidgetsBinding.instance.addPostFrameCallback((timestamp) {
          size.value = _key.currentContext.size;
          _overlay.remove();
        });
      });
      return () => null;
    }, [child]);

    if (size == null || size.value == null) {
      return child;
    } else {
      return builder(context, child, size.value);
    }
  }
}

用法:

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

class HomeView extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final change = useState<bool>(false);
    final normal = Container(
      color: Colors.blueAccent,
      height: 200.0,
      width: 200.0,
    );
    final big = Container(
      color: Colors.redAccent,
      height: 300.0,
      width: 200.0,
    );

    return Column(
      children: [
        Container(
          alignment: Alignment.center,
          child: ChildSizeWidget(
            child: change.value ? big : normal,
            builder: (context, child, size) => AnimatedContainer(
              alignment: Alignment.center,
              child: SingleChildScrollView(child: child),
              duration: Duration(milliseconds: 250),
              height: size.height,
            ),
          ),
          color: Colors.grey,
        ),
        FlatButton(
          child: Text('Toggle child'),
          onPressed: () => change.value = !change.value,
          color: Colors.green,
        ),
      ],
    );
  }
}

我有一个包含多个选项的菜单,它们有不同的高度,在动画的帮助下这没关系,它对我来说真的很好。

演示


推荐阅读