【问题标题】:Child inside Column shrinkwrap when height is short and scrollable when height is overflow高度短时列收缩包装内的子级,高度溢出时可滚动
【发布时间】:2021-08-12 14:38:53
【问题描述】:

假设有一个始终适合其子级大小的 Column 小部件。 ContentWidget 是一个动态大小的小部件。当高度小于屏幕尺寸时,ContentWidget 会显示其高度;并且当它的高度达到屏幕大小溢出时将允许滚动。

有什么方法可以获得这个布局吗?

我遇到过这种设计很多次,我使用过的最简单的解决方案是在构建期间使用 MultiChildLayout 来获取高度并再次调用它的重建,但这不是一个好的解决方案,因为这需要绘制一次.只是想知道是否有更精确的方法可以做到这一点。谢谢!

例如。

短:

长:

白色背景是整个屏幕。 红+黄是列

红色+黄色显示为它的高度,除非黄色太高以至于Column(红色+黄色)大于屏幕(白色区域),然后黄色部分将是可滚动的

更新: 我试过下面的代码,但是 singleChildScrollView 会溢出底部。你有什么建议吗?

 @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.yellow,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        mainAxisSize: MainAxisSize.min,
        children: [
          Text('header'),
          SingleChildScrollView(
              child: Text(
                  'long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long text')),
          Text('footer'),
        ],
      ),
    );
  }
}

【问题讨论】:

  • 不是 100% 确定我理解您的问题。布局问题通常有助于显示问题的图片并在问题的上下文中表达问题。而不是要求一个可能实际上不是实现目标的正确方法的特定 a/b。如果您修改,很高兴再看一遍。
  • 谢谢你,@Kent。希望这对您来说更容易理解。 :-)
  • Tran 给出了正确答案。见他的下文。您只需将滚动视图放在 CenterWidget 中。因为页脚是固定的,所以您无需担心大小。如果页脚需要在 CenterWidget 大小上加深,那将更加困难。
  • @Kent,这个方法在溢出时似乎无法滚动。你有什么建议吗?谢谢!
  • 将中心小部件包裹在单个子滚动视图中

标签: flutter flutter-layout


【解决方案1】:

这是您的示例。您缺少的关键是一个名为 Flexible 的小部件。对于这些类型的情况,它是一个重要的 Widget,您将在从事 Flutter dev 一段时间后了解它。

      import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final exampleText = Text(
      'long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long text');
  List<Widget> content = [];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Container(
            child: Center(child: Text('header')),
            color: Colors.red,
          ),
          Flexible(
            child: SingleChildScrollView(
                child: Container(
              color: Colors.yellow,
              child: Column(children: content),
            )),
          ),
          Container(
            child: Center(child: Text('footer')),
            color: Colors.red,
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          setState(() {
            content.add(exampleText);
          });
        },
      ),
    );
  }
}

Official Flutter video about it.

【讨论】:

  • 谢谢!通常 Flexible 可能适用于其他小部件,但 SingleChildScrollView 无法计算其子级的大小,并将采用视口的最大高度。在这种情况下使用 Flexible 或 Expanded 会占用尽可能多的空间,当子高度较小时它不会缩小,如下所示:imgur.com/a/PCsO7Or
  • 是的,您不需要缩小滚动视图以适应内容,对吧?我在要求中的任何地方都没有看到这一点
  • 是的,滚动视图(或中心小部件)需要在短时适应内容高度;只有当它足够长溢出时才能滚动。red + yellow is showing as its height unless yellow is too high that let the Column(red+yellow) is larger than the screen (white area), then the yellow part will be scrollable
  • @CbL 如果我的演示中的内容很小,它是不可滚动的。你是不是也说footer需要上移,scrollview大小除了不滚动还需要变小?
  • 是的,黄色区域小时显示实际高度(不是Flexible收起后的高度)。
【解决方案2】:
@override
Widget build(BuildContext context) {
return Container(
  // Add this line
  constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height),
  // If there was an AppBar, subtrach with AppBar().preferredSize.height
  // and maybe you need to subtract with status bar height: MediaQuery.of(context).padding.top
  // E.g. MediaQuery.of(context).size.height - AppBar().preferredSize.height - MediaQuery.of(context).padding.top
  color: Colors.yellow,
  child: Column(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    mainAxisSize: MainAxisSize.min,
    children: [
      Text('header'),
      SingleChildScrollView(
          child: Text(
              'long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long text')),
      Text('footer'),
    ],
  ),
);

} }

【讨论】:

  • 谢谢!但问题是,如果我们像这样使用 singleChildScrollView,文本部分无法像我在问题上上传的屏幕截图那样滚动。
【解决方案3】:
      Container(
          color: Colors.yellow,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            mainAxisSize: MainAxisSize.min,
            children: [
              Text('header'),
              Expanded(
                child: SingleChildScrollView(
                  child: Text(
                      'afdfasff long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long  long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long text'),
                ),
              ),
              Text('footer'),
            ],
          ),
        )

【讨论】:

  • 我试过你的方法,这个方法溢出时好像不能滚动,问题中更新了细节。你有什么建议吗?谢谢!
  • 谢谢!我试过你的回答。问题是当内容很短时它无法显示为内容高度。像这样:imgur.com/a/ibo4bkM
  • 对不起。我不明白你的问题到底是什么。数据太短不能滚动,我认为这是合理的。
  • 有两种情况: 1. 当数据较短时(即整个Column没有溢出),居中的文本小部件会准确显示它的高度(不包括Expanded扩展的区域) 2.当数据长到足以溢出时,只有中心文本小部件可以滚动 case 1: i.stack.imgur.com/0Xc3i.png case 2: i.stack.imgur.com/MqXzY.png
  • 让我们将 Expand 替换为灵活。
猜你喜欢
  • 2010-12-12
  • 2013-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-22
  • 2012-04-26
  • 2019-04-06
  • 2015-01-17
相关资源
最近更新 更多