调整父小部件的大小以适应 Flutter 中的子帖子“变换”

Posted

技术标签:

【中文标题】调整父小部件的大小以适应 Flutter 中的子帖子“变换”【英文标题】:Resizing parent widget to fit child post 'Transform' in Flutter 【发布时间】:2020-09-23 09:28:03 【问题描述】:

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

这使用了诸如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),
          ),
        ),
      ),
    );
  

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

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

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

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

【问题讨论】:

什么是父小部件,您将整个代码返回到哪里? 感谢@Chinky 添加图片。由于我目前的评分,我不能。 @BigRedSwitch 与评分无关,只需在图片链接前加一个“”即可:D @Chinky Sight - 我试过了。拒绝! D-: 您找到解决方案了吗?遇到了完全相同的问题,不明白为什么“setState”不会让 Listview.builder 重新计算转换后的瓷砖的高度 【参考方案1】:

对此我有一个棘手的解决方案: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,
        ),
      ],
    );
  

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

【讨论】:

【参考方案2】:

你为什么要使用对齐,正如我在你的代码中看到的那样,没有设置或使用属性来对齐任何东西。因此,请尝试移除 Transform 周围的 Align 小部件。 因为根据文档,Transform 是这样一个小部件,它试图与他们的孩子一样大小。这样就可以满足你的要求了。

有关更多信息,请查看此文档:https://flutter.dev/docs/development/ui/layout/box-constraints

希望对你有帮助!

【讨论】:

对齐只是为了防止父小部件在整个屏幕上缩放。它与这里的问题并不真正相关。我已经尝试删除它 - 没有任何区别。有关详细信息,请参阅上面的“编辑”。

以上是关于调整父小部件的大小以适应 Flutter 中的子帖子“变换”的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Flutter 中的子小部件调用父小部件功能

Flutter - 无法从父小部件更改子状态

如何从子小部件调用父小部件中的函数 |扑

如何在 AppBar 中包装子小部件以获得更大的子高度和 Flutter 中的填充

如何布局 GridView.count 以便小部件从 Flutter 中的父小部件顶部开始构建?

如何更轻松地实现一个 Flutter 布局?