簡體   English   中英

如何使用 Flutter 實現位置:粘性和底部 0?

[英]How to implement position: sticky and bottom 0 with Flutter?

我想建立一個帶有粘性頁腳的列表視圖,如本文的“粘到底?!” 在顫振。

在此處輸入圖像描述

在 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);
    }
  }
}

試試 Column 有三個孩子, Header 和 Footer 有一個特定的大小, ListView 占據剩余空間。

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

滾動將應用於 ListView。

嘗試這個

import 'package:flutter/material.dart';

class Sticky extends StatefulWidget {
  Sticky({Key key}) : super(key: key);

  _StickyState createState() => _StickyState();
}

class _StickyState extends State<Sticky> {
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Stack(
          children: <Widget>[
            Positioned(
              child: Container(
                color: Colors.black38,
                height: 60,
                width: MediaQuery.of(context).size.width,
                child: Text('Header'),
              ),
              top: 0,
            ),
            Positioned(
              child: Container(
                child: Text('Content'),
              ),
              top: 60,
            ),
            Positioned(
              child: Container(
                color: Colors.black38,
                height: 60,
                width: MediaQuery.of(context).size.width,
                child: Text('Footer'),
              ),
              bottom: 0,
            ),
          ],
        ),
      ),
    );
  }
}

將 Stack() 與 ListView 放在一起,然后在底部放置一個 Container 的 Column 怎么樣? 這可能不是您期望的答案,但它會按照預期的方式工作。 我試過了:

Stack(
    children: <Widget>[
      ListView.builder(
        itemCount: 30,
        itemBuilder: (context, index) {
          return Container(
            child: Text(
                "Text\n"),
          );
        },
      ),
      Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          Container(
            width: double.infinity,
            height: 60,
            child: Text("That's the footer"),
            color: Colors.blue,
          ),
        ],
      )
    ],
  )

試試這個包

https://pub.dev/packages/sticky_infinite_list

在描述中有一個示例應用程序的鏈接,您可以在其中使用它。

這個包支持頂部和底部定位的粘性標題,也可以左右兩個位置。 它默認覆蓋內容,但您可以在內容底部添加邊距,以防止覆蓋以及當標題到達其最小偏移位置時

要實現這樣的視圖,我建議使用Slivers

好處

  1. 粘性頁眉/頁腳。
  2. 無限正文/內容滾動。

檢查下面的代碼

import 'package:flutter/material.dart';

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          SliverList(
            delegate: SliverChildListDelegate(
              [
                Container(
                  width: double.infinity,
                  height: 50,
                  color: Colors.orangeAccent,
                  child: Center(
                    child: Text(
                      'Header',
                      style: TextStyle(color: Colors.white, letterSpacing:4),
                    ),
                  ),
                ),
                ListView.builder(
                  shrinkWrap: true,
                  itemCount: 100,
                  itemBuilder: (BuildContext context, int index) {
                    return ListTile(
                      title: Center(child: Text('$index')),
                    );
                  },
                ),
              ],
            ),
          ),
          SliverFillRemaining(
            hasScrollBody: false,
            child: Align(
              alignment: Alignment.bottomCenter,
              child: Container(
                width: double.infinity,
                height: 50,
                color: Colors.blueAccent,
                child: Center(
                  child: Text(
                    'Footer',
                    style: TextStyle(color: Colors.white, letterSpacing: 4),
                  ),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }
}

在此處輸入圖像描述

在此處輸入圖像描述

在此處輸入圖像描述

在此處輸入圖像描述

有關更多詳細信息,請查看此處:

https://itnext.io/create-a-header-footer-with-scrollable-body-view-in-flutter-5551087270de

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM