首页 > 解决方案 > 如何使用 Flutter 实现位置:粘性和底部 0?

问题描述

我想建立一个带有粘性页脚的列表视图,如本文的“粘到底?!” 在颤振。

在此处输入图像描述

在 CSS 中,

.main-footer{     
     position: sticky; 
     bottom: 0;
}

但是如何处理 Flutter?

我想要的是

  1. 可滚动的大内容
  2. 页脚(粘性)
  3. 可滚动的大内容

1 和 2 在 First 中可见(可滚动内容和固定页脚)。滚动到 1 的末尾后,页脚 (2) 变得不固定。其余内容 (3) 将显示在页脚 (2) 下方。

我尝试使用CustomScrollView来实现上面的功能,但未在列表上方绘制页脚按钮。

在此处输入图像描述

代码

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.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: 'Fixed footer',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        body: _FixedFooterDemo(),
        floatingActionButton: FloatingActionButton(
          onPressed: () {},
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

class _FixedFooterDemo extends StatelessWidget {
  const _FixedFooterDemo({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: <Widget>[
        SliverAppBar(
          title: Text('Fixed footer'),
        ),
        SliverList(
          delegate: SliverChildListDelegate(List.generate(20, _buildListItem)),
        ),
        SliverStickyFooter(
          child: Center(
            child: RaisedButton(
              onPressed: () {},
              child: Text('Fixed under list button'),
            ),
          ),
        ),
        SliverFillRemaining(
          child: Container(
            color: Colors.yellow,
            child: Center(
              child: Text('below space'),
            ),
          ),
        ),
      ],
    );
  }

  ListTile _buildListItem(int i) {
    return ListTile(
      title: Text(
        'Item $i',
      ),
      subtitle: Text(
        'Sit est ipsum consequat sit ex. Minim magna laborum dolore aliqua sit dolore velit sint fugiat. Culpa officia tempor proident minim aliquip nisi reprehenderit ullamco duis mollit. Aute velit irure ut Lorem pariatur anim mollit cillum dolor irure quis. Eu officia dolore deserunt do est cupidatat duis elit. Pariatur magna reprehenderit aliquip ea irure Lorem sunt aute.',
        maxLines: 2,
      ),
    );
  }
}

class SliverStickyFooter extends SingleChildRenderObjectWidget {
  const SliverStickyFooter({
    Key key,
    Widget child,
  }) : super(key: key, child: child);

  @override
  RenderSliverStickyFooter createRenderObject(BuildContext context) =>
      RenderSliverStickyFooter();
}

class RenderSliverStickyFooter extends RenderSliverSingleBoxAdapter {
  /// Creates a [RenderSliver] that wraps a [RenderBox] which is sized to fit
  /// the remaining space in the viewport.
  RenderSliverStickyFooter({
    RenderBox child,
  }) : super(child: child);

  @override
  void performLayout() {
    child?.layout(
      constraints.asBoxConstraints(),
      parentUsesSize: true,
    );

    final paintedChildSize =
        calculatePaintOffset(constraints, from: 0.0, to: child.size.height);
    assert(paintedChildSize.isFinite);
    assert(paintedChildSize >= 0.0);
    geometry = SliverGeometry(
      scrollExtent: child.size.height,
      paintExtent: paintedChildSize,
      maxPaintExtent: paintedChildSize,
      hasVisualOverflow: true,
      paintOrigin: -child.size.height + paintedChildSize,
      visible: true,
    );

    if (child != null) {
      setChildParentData(child, constraints, geometry);
    }
  }
}

标签: flutter

解决方案


试试 Column 有三个孩子,Header 和 Footer 有一个特定的大小,ListView 占据剩余的空间。

        Column(
                children: [
                  Container(height: 100, child: HeaderWidget),
                  Expanded(child: ListView.builder(...)),
                  Container(height: 100, child: FooterWidget),
                ]

滚动将应用于 ListView。


推荐阅读