当孩子的尺寸超过屏幕尺寸时处理堆栈

时间:2021-04-23 23:54:34

标签: flutter flutter-layout

当孩子的尺寸小于屏幕尺寸时,使用 Stack 非常容易控制布局。但是当孩子的身高大于屏幕尺寸时,就需要使用SingleChildScrollView。但是如果我使用它,整个屏幕会变白并产生如下所示的错误。

在这些情况下使用 StackSingleChildScrollView 时如何处理布局。 任何帮助是极大的赞赏。谢谢。

示例代码

import 'package:flutter/material.dart';

void main(List<String> args) {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          child: SingleChildScrollView(
            child: Stack(
              fit: StackFit.expand,
              children: [
                _Background(),
                Positioned(left: 0, top: 100, child: WidgetA()),
                Positioned(left: 0, top: 270, child: WidgetB()),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class _Background extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height,
      width: MediaQuery.of(context).size.width,
    );
  }
}

class WidgetA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: randomHeight(),
      width: MediaQuery.of(context).size.width,
      color: Colors.purple,
      child: Center(
        child: Text('Widget A'),
      ),
    );
  }
}

class WidgetB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 250,
      width: MediaQuery.of(context).size.width,
      color: Colors.yellow,
      child: Center(
        child: Text('Widget B'),
      ),
    );
  }
}

错误

════════ Exception caught by rendering library ═════════════════════════════════
RenderBox was not laid out: RenderRepaintBoundary#2e73f relayoutBoundary=up1 NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1940 pos 12: 'hasSize'

The relevant error-causing widget was
Scaffold
lib/main.dart:11
════════════════════════════════════════════════════════════════════════════════

3 个答案:

答案 0 :(得分:2)

原因:

SingleChildScrollView 提供无限空间。

堆栈自身大小以包含所有未定位的子项,这些子项根据对齐方式定位(默认为从左到右环境中的左上角和从右到左环境中的右上角环境)。然后根据它们的顶部、右侧、底部和左侧属性相对于堆栈放置已定位的子项。

小部件永远膨胀。

它也会导致 StackRender 算法出现问题,因为它会处理 Zenith。

Read more in the api documentation here.

解决方案给它一个约束,比如一个 SizedBox();

答案 1 :(得分:1)

用容器包裹您的堆栈并使用 MediaQuery 定义其高度和宽度,然后用一列包裹容器。

答案 2 :(得分:1)

首先整个屏幕变白,因为 StackFit.expand 告诉堆栈尽可能地扩展,并且因为它在 SingleChildScrollView 内是无穷大并且无法处理。

第二个是堆栈高度是根据它的孩子定义的,而不计算位置小部件的高度,比如css position:absolute;,如果你熟悉的话,剩下的就是你的_Background whcih定义堆栈高度的小部件..

所以现在 SingleChildScrollView 和它的孩子有(屏幕高度)高度 = 没有滚动,为了解决这个问题,我们必须指定足够的高度,让我们定位的小部件出现在我们的堆栈中,以便我们的堆栈能够滚动进来。

如何修复

第一个在您的堆栈中将适合更改为

 child: Stack(
            fit: StackFit.loose,

第二你的背景,负责上面提到的高度

class _Background extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      height: MediaQuery.of(context).size.height + 250, // <-- change this
      width: MediaQuery.of(context).size.width,
    );
  }
}