Flutter:SliverPersistentHeader在滚动时重建自己

时间:2018-05-03 17:48:49

标签: flutter

我为我遇到的这个问题建立了一个小测试示例。您可以从下面的gif看到,Flutter应用程序顶部只有一个标题。当我下拉刷新时,标题不会重建。但是,当我向上推动标题时,标题会重建多次。另请注意,我没有在我的代码中的任何地方调用setState(),因此当我向上推滚动视图时,我不确定它是如何知道它需要重建自身。

我想首先不重建自己,因为没有理由重建自己。它是静态/无状态的,根本不应该改变。标题的大小也应该不会改变(因此,expandHeight和collapsedHeight在136.0处相同)。

enter image description here

以下是我用来重新创建的示例代码:

import 'package:meta/meta.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:math' as math;
import 'dart:async';

class _TestHeader extends SliverPersistentHeaderDelegate {
  _TestHeader({
    @required this.collapsedHeight,
    @required this.expandedHeight,
    @required this.showHeading,
  });

  bool showHeading;
  final double expandedHeight;
  final double collapsedHeight;

  @override
  double get minExtent => collapsedHeight;

  @override
  double get maxExtent => math.max(expandedHeight, minExtent);

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    print("rebuilding headings");
    return new SafeArea(
        child: Column(children: <Widget>[
      const SizedBox(height: 24.0),
      new GestureDetector(
        onTap: () {
        },
        child: new Container(
          decoration: const BoxDecoration(
            color: CupertinoColors.white,
            border: const Border(
              top: const BorderSide(color: const Color(0xFFBCBBC1), width: 0.0),
              bottom:
                  const BorderSide(color: const Color(0xFFBCBBC1), width: 0.0),
            ),
          ),
          height: 44.0,
          child: new Padding(
            padding:
                const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
            child: new SafeArea(
              top: false,
              bottom: false,
              child: new Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: const <Widget>[
                  const Text(
                    'This is my heading',
                    style: const TextStyle(color: CupertinoColors.activeBlue, fontSize: 16.0),
                  )
                ],
              ),
            ),
          ),
        ),
      ),
    ]));
  }

  @override
  bool shouldRebuild(@checked _TestHeader oldDelegate) {
//    return false;
    return expandedHeight != oldDelegate.expandedHeight ||
        collapsedHeight != oldDelegate.collapsedHeight;
  }
}

class TestHeaderPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new TestHeaderState();
  }
}


class TestHeaderState extends State<TestHeaderPage> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new CupertinoPageScaffold(
      //i will need to convert this to a sliver list to make this work properly.
        backgroundColor: const Color(0xFFEFEFF4),
        navigationBar: new CupertinoNavigationBar(
          middle: new Text('Test Headers'),
        ),
        child: new SafeArea(
          child: new CustomScrollView(slivers: <Widget>[
            new CupertinoRefreshControl(onRefresh: () {
              print("pulling on refresh");
              return Future<void>(() {});
                }),
            new SliverPersistentHeader(
                delegate: new _TestHeader(
                    collapsedHeight: 136.0,
                    expandedHeight: 136.0,
                    showHeading: true)),
          ]),
        ));
  }

}

1 个答案:

答案 0 :(得分:3)

这是完全正常的。

您的_TestHeader 小部件。仅仅因为它具有build方法并不意味着它是一个。 :)

您扩展了SliverPersistentHeaderDelegate,用于构建SliverPersistentHeader

事情是:SliverPersistentHeader 小部件。这是一个条子,这是一种在屏幕上呈现内容的不同方式。

而且,在SliverPersistentHeader的情况下,只要滚动偏移发生变化,它就会重建一种特定的条子。也就是说,可能处理滚动特定的动画。 如向上滚动使标题消失。然后向下滚动以使其快速恢复。