Flutter 中类似 Web 的页脚

问题描述 投票:0回答:2

我正在尝试实现一个简单的网页视图,带有应用栏、内容和页脚。 我正在努力解决页脚的位置。

我想要什么:

  • 如果内容没有填满整个屏幕,页脚应粘在底部
  • 如果内容大于屏幕,则只有向下滚动到底部才会显示页脚
  • 如果内容没有填满整个屏幕,内容将显示在应用栏和页脚之间的中心。

我看到几个答案对我的第2个要求有帮助(例如如何使用Flutter创建带有固定页脚的滚动视图?),但对第三个要求没有帮助:在我找到的答案中,内容不包含整个可用空间,并粘在顶部。

到目前为止我找到的解决方案有效:它具有我想要的行为。但不太优雅。

我使用了以下结构:

Scaffold(
    body: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        SizedBox(
          height: 100,
          child: MyAppBar(),
        ),
        Expanded(
          child: SingleChildScrollView(
            child: Column(
              children: [
                SizedBox(height: bottomSizedBoxHeight),
                Column(
                  key: childrenColumnKey,
                  children: [
                    Container(color: Colors.red, width: 300, height: 300),
                    Container(color: Colors.green, width: 300, height: 300),
                    Container(color: Colors.amber, width: 300, height: 300),
                  ],
                ),
                SizedBox(height: bottomSizedBoxHeight),
                const SizedBox(
                  height: 150,
                  child: MyFooter(),
                ),
              ],
            ),
          ),
        ),
      ],
    ),
  );

在这里您可以看到 2 个 SizedBox,其高度是在运行时计算的。

计算如下:

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  scheduleMicrotask(() {
    double pageWidgetsHeight = childrenColumnKey.currentContext?.size?.height ?? 0;

    // Total height of space available is screen height - appBar (100) - footer (150)
    double totalHeight = max(0, MediaQuery.of(context).size.height - pageWidgetsHeight - 100 - 150);

    setState(() {
      topSizedBoxHeight = totalHeight / 2;
      bottomSizedBoxHeight = totalHeight / 2;
    });
  });
}

正如你所看到的,不是很优雅。我计算小部件构建后的总剩余空间,以创建 2 个具有剩余空间的盒子。

这给了我只有 1 个红色方块的结果:

Footer with 1 square

这是当我添加其他方块时,页脚被正确隐藏:

footer is hidden

但我不喜欢我实现这一目标的方式。如果有人知道如何实现这一点!

谢谢!

flutter layout footer
2个回答
1
投票

我终于找到了解决方案:使用

Slivers

这是实现此目的的代码示例:

Scaffold(
  appBar: AppBar(
    title: Text('Title'),
  ),
  body: CustomScrollView(
    slivers: [
      SliverList(
        delegate: SliverChildListDelegate(
          [
              Column(
              children: [
                Container(color: Colors.red, width: 300, height: 300),
                Container(color: Colors.green, width: 300, height: 300),
                Container(color: Colors.amber, width: 300, height: 300),
              ],
            ),
          ],
        ),
      ),
      SliverFillRemaining(
        hasScrollBody: false,
        child: Align(
          alignment: Alignment.bottomCenter,
          child: Container(color: Colors.orange),
        ),
      )
    ],
  ),
);

0
投票

这将是另一种方式...我不知道它是否更漂亮:D

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

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

  @override
  Widget build(BuildContext context) {
    final red = Colors.red.withOpacity(0.5);
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: MyHome(),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Container(
      height: MediaQuery.of(context).size.height,
      color: Colors.white,
      child: Column(
        children: [
          Expanded(
            child: ListView(
              children: [
                LayoutBuilder(builder: (context, constraints) {
                  return SizedBox(
                    height: MediaQuery.of(context).size.height -
                        56, //56==height of AppBar
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Container(color: Colors.red, width: 300, height: 300),
                        // Container(color: Colors.green, width: 300, height: 300),
                        // Container(color: Colors.amber, width: 300, height: 300),
                        Spacer(),
                        AppBar(),
                      ],
                    ),
                  );
                }),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.