Flutter - 使用 Column/Expanded/ListView 的布局问题

Posted

技术标签:

【中文标题】Flutter - 使用 Column/Expanded/ListView 的布局问题【英文标题】:Flutter - Layout problem using Column/Expanded/ListView 【发布时间】:2020-12-18 11:34:25 【问题描述】:

我对 Flutter 很陌生,我似乎无法解决这个问题。

我想显示我的自定义卡片式 Ink 容器的 ListView 并且几乎实现了它。但是,当我向下滚动时,ListView 会延伸到我的 Text 小部件(列中的前一项)后面:

Expanded widget behind text widget

滚动时查看“图库”文本的后面: Animated GIF showing undesired behavior

我希望我的 ListView 小部件滚动,而容器不显示在“图库”文本后面。

我尝试不使用 Expanded 小部件(ListView.builder() 直接在 Column 子项下),但我在调试控制台中收到此错误消息:

════════ 渲染库捕获的异常 ═════════════════════════════════ RenderBox 没有布局: RenderRepaintBoundary#8dc77 relayoutBoundary=up8 NEEDS-PAINT 'package:flutter/src/rendering/box.dart':断言失败:第 1702 行 pos 12: 'hasSize' 相关的导致错误的小部件是 专栏

而且列表根本不显示。

这是我的代码:

class Gallery extends StatelessWidget 

  final List<_ChallengeCard> challengestest = [
    _ChallengeCard(title: 'Challenge #1', subtitle: 'Completed on 13/11/1978'),
    _ChallengeCard(title: 'Challenge #2', subtitle: 'Completed on 12/18/2043'),
    _ChallengeCard(title: 'Challenge #3', subtitle: 'Current challenge'),
    _ChallengeCard(title: 'Challenge #4', subtitle: 'Locked'),
    _ChallengeCard(title: 'Challenge #5', subtitle: 'Locked'),
    _ChallengeCard(title: 'Challenge #6', subtitle: 'Locked'),
    _ChallengeCard(title: 'Challenge #7', subtitle: 'Locked'),
    ];

    Widget build(BuildContext context) 
        return Scaffold(
          body: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              mainAxisSize: MainAxisSize.max,
              children: [
                Text(
                'Gallery',
                style: GoogleFonts.alexBrush(fontSize: 55),
                textAlign: TextAlign.center,
                ),
                Expanded(
                  child: ListView.builder(
                    itemCount: challengestest.length,
                    itemBuilder: (context, index)
                    return Container(
                      padding: EdgeInsets.symmetric(vertical: 8.0),
                      child: InkWell(
                        onTap: (),
                        child: challengestest[index]
                      ),
                    );
                    ,
                  ),
                ),
              ],
            ),
        );
      
    

还有一些额外的类,以便您可以看到 ListView 项目的具体内容(但我怀疑它们与问题有关):

class _ChallengeCard extends StatelessWidget 
  _ChallengeCard(
    Key key,
    this.title,
    this.subtitle,
  ) : super(key: key);

  final String title;
  final String subtitle;

  @override
  Widget build(BuildContext context) 
    return Ink(
      padding: EdgeInsets.all(11.0),
      decoration: BoxDecoration(
        color: Color(0xFF11001A),
        borderRadius: BorderRadius.all(Radius.circular(10.0))),
      child: Container(
        alignment: Alignment.topLeft,
        child: Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 8.0),
            child: Icon(Icons.star,color: Colors.white, size: 40.0,),
          ),
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children:<Widget>[
              Text(
                '$title',
                style: GoogleFonts.lora(fontSize: 25),
              ),
              Text(
                '$subtitle',
                style: GoogleFonts.lora(fontSize: 15),
              ),
            ],
          ),
        ],
        ),
      ),
    );
  

“gallery”类是从 main.dart 文件中调用的(这就是为什么整个应用程序中有一个底部导航栏的原因),但我没有包含它,因为它与问题无关。

提前致谢!

【问题讨论】:

目前尚不清楚您所描述的不良行为来自图像,并且您提供的代码不会显示显示的小部件的想法使情况更加复杂。如果您提供了一个 gif 而不是显示不良行为的静态图像,或许可以? @Abion47 我添加了一个 GIF 来显示不受欢迎的行为以及更多代码。谢谢! 【参考方案1】:

您也可以通过将小部件包装在单个子滚动视图中来使文本滚动

   ...

   SingleChildScrollView(// add a scrollview
                child: 
              Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  mainAxisSize: MainAxisSize.max,
                  children: [
                    Text(
                    'Gallery',
                 style: GoogleFonts.alexBrush(fontSize: 55),
                    textAlign: TextAlign.center,
                    ), 
                    //remove the expanded widget
                  ListView.builder(
                    shrinkWrap: true, // make shrikwrap true
                        physics: NeverScrollableScrollPhysics(), // add this physics so it won't scroll
                        itemCount: challengestest.length,
                        itemBuilder: (context, index)
                        return Container(
                        ... // rest of your code here
);
),
]))

【讨论】:

感谢您的回复!这确实可以很好地使文本与卡片一起滚动,但我希望保持文本像现在一样静态。我只是不希望这些框在向上滚动时出现在文本后面(如 GIF 中所示)。【参考方案2】:

我终于通过使用 AppBar 小部件而不是“图库”标题的 Text 小部件来让它工作。

Scaffold 不再包含 Column 小部件,仅包含 ListView.Builder:

  Widget build(BuildContext context) 
    return Scaffold(
      body: ListView.builder(
                shrinkWrap: true,
                itemCount: challengestest.length,
                itemBuilder: (context, index)
                  return Container(
                    padding: EdgeInsets.symmetric(vertical: 8.0),
                    child: InkWell(
                      onTap: (),
                      child: challengestest[index]
                    ),
                  );
                ,
              ),
    );
  

文本“Gallery”已被移动为经过大量修改的 AppBar,带有 Stack 小部件以保留其外观:

   Stack(
      children: <Widget>[
        Image.asset(
            "assets/images/bgpurple.jpeg",
            height: MediaQuery.of(context).size.height,
            width: MediaQuery.of(context).size.width,
            fit: BoxFit.cover,
          ),
        Scaffold(
          appBar: PreferredSize(
            preferredSize: Size.fromHeight(85.0),
            child: AppBar(
              automaticallyImplyLeading: false,
              elevation: 0.0,
              backgroundColor: Colors.transparent,
              centerTitle: true,
              flexibleSpace: Padding(
                padding: const EdgeInsets.only(top: 60.0),
                child: Center(
                  child: Text(
                    _myPageTitles[_selectedIndex],
                    style: GoogleFonts.alexBrush(
                      fontSize: 45, 
                      color: Colors.white,
                      )
                    ),
                ),
              ),
            ),
          ),

【讨论】:

以上是关于Flutter - 使用 Column/Expanded/ListView 的布局问题的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 使用 google_sign_in 库时未找到 <Flutter/Flutter.h>

Flutter——如何使用 html 链接渲染 Flutter 文本 [重复]

flutter系列之:在flutter中使用导航Navigator

Flutter - 无法在flutter web中使用动态链接

无法使用 Flutter 1.22.3 编译 Flutter 应用程序

Flutter中使用flutter_html解析html文件