创建粘性站点页脚

Creating a Sticky Site Footer

我无法找到任何有关使用 Flutter/Dart 创建页脚导航栏的文档。我知道“crossAxisAlignment: CrossAxisAlignment.end”可用于将内容拉到列的底部。但是,我不确定如何呈现粘在屏幕底部的网站页脚。在 flex 和 css grid 中有多种解决方案,但不清楚在该平台上的实现方式。

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override

  Widget build(BuildContext context) {

    Widget siteLogo = new Container(
      padding: const EdgeInsets.only(top: 100.0),
      child: new Image.asset(
        'images/logo.png',
        width: 180.0,
        height: 180.0,
      ),
    );

    Widget titleTextSection = new Container(
      padding: const EdgeInsets.only(left: 80.0, right: 80.0, top: 30.0, bottom: 20.0),
        child: new Text(
        ''' Welcome to The Site''',
            textAlign: TextAlign.center,
        style: new TextStyle(
          fontSize: 35.0,
          fontWeight: FontWeight.w500,
        ),
      ),
    );

    Widget subtitleTextSection = new Container(
      padding: const EdgeInsets.only(left: 40.0, right: 40.0, bottom: 40.0),
      child: new Text(
        '''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec imperdiet Donec imperdiet.''',
        textAlign: TextAlign.center,
        style: new TextStyle(
            fontSize: 15.0,
            fontWeight: FontWeight.w400
        ),
      ),
    );


//    footer
    Column signInLink(String label) {

      return new Column(
        mainAxisAlignment: MainAxisAlignment.center,

        children: [
          new Container(
            child: new Text(
              label,
              style: new TextStyle(
                  fontSize: 16.0,
                  fontWeight: FontWeight.w400,
                  color: const Color(0xFFf735e9)
              ),
            ),
          ),
        ],
      );
    }


    Column existingAccountLink(String label) {

      return new Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          new Container(
            child: new Text(
              label,
              style: new TextStyle(
                  fontSize: 16.0,
                  fontWeight: FontWeight.w400,
                  color: const Color(0xFFeceff1)
              ),
            ),
          ),
        ],
      );
    }

    Widget footer = new Container(
      height: 50.0,
      decoration: new BoxDecoration(color: Colors.black),
      child: new Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          existingAccountLink('Already have an account?'),
          signInLink('SIGN IN'),
        ],
      ),
    );

    return new MaterialApp(
      title: 'Flutter Demo',
      home: new Scaffold(
        body: new Container(
          decoration: new BoxDecoration(
            image: new DecorationImage(
              image: new AssetImage('images/backgroundimg.jpg'),
              fit: BoxFit.cover,
            ),
          ),
          child: new ListView(
            children: [
              siteLogo,
              titleTextSection,
              subtitleTextSection,
              footer,
            ],
          ),
        )
      ),
    );
  }
}

如您所见,我目前正在使用 ListView 来布置小部件。我现在唯一能想到的是将整个 ListView 放在一个列中,crossAxisAlign 到 End,这样所有内容都被下拉,然后相对于页脚设置每个小部件的样式。必须有更好的方法吗?

由于您使用的是 Scaffold,因此您可以使用 bottomNavigationBar 获得一个 'sticky' 底部小部件。 (如果你愿意,可以使用 BottomNavigationBar

new Scaffold(
  appBar: new AppBar(title: new Text("Title")),
  body: new ListView.builder(
    itemBuilder: (context, index) {
      return new ListTile(
        title: new Text("title $index"),
      );
    },
  ),
  bottomNavigationBar: new Container(
    height: 40.0,
    color: Colors.red,
  ),
);

或者你的

The only thing I can think of right now is to put the whole ListView in a single column

一点也不坏。这就是 Flutter 的运作方式。 虽然 MainAxisAlignement.end 不是正确的做法。

您可以在没有脚手架的情况下实现与 bottomNavigationBar 相同的布局,使用 Column 这样:

new Column(
  children: <Widget>[
    new Expanded(
      child: new ListView.builder(
        itemBuilder: (context, index) {
          return new ListTile(
            title: new Text("title $index"),
          );
        },
      ),
    ),
    new Container(
      height: 40.0,
      color: Colors.red,
    ),
  ],
),

当您有一个需要列表视图的项目列表时,使用列表视图是一个很好的选择。有时布局中的其他项目可能是固定的,不需要列表视图。例如使用列。

关于如何使用 stack.

实现固定底部页脚的示例
 @override
   Widget build(BuildContext context) {
    return new Material(
      child: Scaffold(
        body: Stack(
        children : <Widget> [
         Text("Top positioned text"),
         Column(
            children : <Widget> [
               Text("Column:Top positioned text"),
               Text("Column:Top positioned text")
             ]
            ),
         Positioned(
            bottom : 0,
            child: Text("Bottom positioned text")
         )
        ]
      )
    }

您可以使用 flutter_layouts

中的页脚

粘性页脚可能难以实现。由于您必须知道页脚的高度,因此无法在 build() 函数中执行此操作。

试试下面的 flutter 包。

https://github.com/softmarshmallow/flutter-layouts/tree/master/lib/src/footer https://github.com/softmarshmallow/flutter-layouts/

由此,您可以将页脚与脚手架底部导航一起使用。 example

import 'package:flutter_layouts/flutter_layouts.dart';
class _FooterScreenState extends State<FooterScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("footer demo"),
      ),
      body: buildBody(),
      bottomNavigationBar: BottomNavigationBar(items: [
        BottomNavigationBarItem(icon: Icon(Icons.add), title: Text("first")),
        BottomNavigationBarItem(icon: Icon(Icons.remove), title: Text("second"))
      ]),
    );
  }

  Widget buildBody() {
    return Footer(
      body: buildContent(),
      footer: buildFooter(),
    );
  }

  Widget buildContent() {
    return ListView.builder(
      itemBuilder: (c, i) {
        return Card(
          margin: EdgeInsets.all(16),
          child: Container(
            padding: EdgeInsets.all(24),
            child: Text("contents"),
          ),
        );
      },
      itemCount: 20,
    );
  }

  Widget buildFooter() {
    return Container(
      padding: EdgeInsets.all(24),
      decoration: BoxDecoration(color: Theme.of(context).primaryColor),
      child: FlatButton(
        onPressed: () {},
        child: Text("Lean more", style: Theme.of(context).textTheme.button.copyWith(
          color: Theme.of(context).colorScheme.onBackground
        ),),
      ),
    );
  }
}