当视口大于最大宽度时,SingleChildScrollView 渲染溢出

SingleChildScrollView rendering overflow when viewport greater than maxwidth

我正在尝试将 Web 内容设置为具有最大宽度(图像中的橙色),并始终填充可用高度,我已经做到了。

然而,当 window 比最大内容宽度更宽,并且 window 高度小于内容、页眉和页脚的总和高度时。我遇到了渲染溢出。 当我所追求的是内容保持其高度并启用滚动时。

注意:如果每个文本只有 1 行,问题似乎就解决了。

我试过使用 CustomeScrollViewSliverFillRemaining,但我遇到了同样的问题。

如有任何帮助,我们将不胜感激。

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Scrollable Layout',
      home: ScrollableLayout(),
    );
  }
}

class ContentWidthContainer extends StatelessWidget {
  final Widget child;

  const ContentWidthContainer({Key? key, required this.child})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.grey,
      child: Align(
        alignment: Alignment.topCenter,
        child: Container(
            color: Colors.orange,
            width: double.infinity,
            constraints: const BoxConstraints(
              maxWidth: 960,
            ),
            padding: const EdgeInsets.symmetric(horizontal: 75),
            child: child),
      ),
    );
  }
}

class ScrollableLayout extends StatelessWidget {
  const ScrollableLayout({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: Theme.of(context).textTheme.bodyText2!,
      child: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints viewportConstraints) {
          return SingleChildScrollView(
            child: ConstrainedBox(
              constraints: BoxConstraints(
                minHeight: viewportConstraints.maxHeight,
              ),
              child: IntrinsicHeight(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    ContentWidthContainer(
                      child: Container(
                          color: Colors.indigo,
                          height: 200,
                          child: const Text('Header: Fixed Height')),
                    ),
                    Expanded(
                      child: ContentWidthContainer(
                        child: Container(
                            color: Colors.white,
                            child: Column(
                              children: const [
                                Text(
                                    'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                              ],
                            )),
                      ),
                    ),
                    ContentWidthContainer(
                      child: Container(
                          color: Colors.indigo,
                          height: 200,
                          child: const Text('Footer: Fixed Height')),
                    ),
                  ],
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

如果页眉和页脚的高度都是200,那么中间内容的高度应该小于400。

height: MediaQuery.of(context).size.height - 400

因此将您的代码更改为

 @override
   Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: Theme.of(context).textTheme.bodyText2!,
      child: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints viewportConstraints) 
        {
          return SingleChildScrollView(
            child: ConstrainedBox(
              constraints: BoxConstraints(
                minHeight: viewportConstraints.maxHeight,
              ),
              child: IntrinsicHeight(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    ContentWidthContainer(
                      child: Container(
                          color: Colors.indigo,
                          height: 200,
                          child: const Text('Header: Fixed Height')),
                    ),
                    Expanded(
                      child: ContentWidthContainer(
                        child: Container(
                            height: MediaQuery.of(context).size.height - 400,
                            color: Colors.white,
                            child: Column(
                              children: const [
                                Text(
                                    'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                              ],
                            )),
                      ),
                    ),
                    ContentWidthContainer(
                      child: Container(
                          color: Colors.indigo,
                          height: 200,
                          child: const Text('Footer: Fixed Height')),
                    ),
                  ],
                ),
              ),
            ),
          );
        },
      ),
    );
  }

将其更改为使用一个只有 2 个子项且对齐方式设置为 SpaceBetween 的列后,当您将宽度设置为 window 但比内容短时,溢出问题就会消失。

class ScrollableSpaceBetweenLayout extends StatelessWidget {
  const ScrollableSpaceBetweenLayout({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: Theme.of(context).textTheme.bodyText2!,
      child: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints viewportConstraints) {
          return SingleChildScrollView(
            child: Container(
              color: Colors.black12, // the background / sides
              constraints: BoxConstraints(
                minHeight: viewportConstraints.maxHeight,
              ),
              child: Column(
                mainAxisSize: MainAxisSize.max,
                children: <Widget>[
                  Container(
                      color: Colors.indigo,
                      height: 200,
                      child: const Align(
                          alignment: Alignment.center,
                          child: Text('Header: Fixed Height'))),
                  Container(
                    color: Colors.orange,
                    constraints: BoxConstraints(
                      maxWidth: 960,
                      minHeight: max(viewportConstraints.maxHeight - 400, 0),
                    ),
                    padding: const EdgeInsets.symmetric(horizontal: 75),
                    child: Container(
                        color: Colors.white,
                        child: Column(
                          mainAxisSize: MainAxisSize.max,
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Column(
                              children: const [
                                Text(
                                    'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                              ],
                            ),
                            Container(
                                child: const Text('spacer'),
                                height: 1,
                                color: Colors.red)
                          ],
                        )),
                  ),
                  Container(
                      color: Colors.indigo,
                      height: 200,
                      child: const Align(
                          alignment: Alignment.center,
                          child: Text('Footer: Fixed Height'))),
                ],
              ),
            ),
          );
        },
      ),
    );
  }
}