Flutter 颤振:SliverPersistentHeader在卷轴上重建自身

Flutter 颤振:SliverPersistentHeader在卷轴上重建自身,flutter,Flutter,我已经为我遇到的这个问题构建了一个小的测试示例。您可以从下面的gif中看到,Flatter应用程序的顶部只有一个标题。当我下拉刷新时,标题不会自行重建。但是,当我向上推收割台时,收割台会多次自我重建。还要注意的是,我没有在代码中的任何地方调用setState(),因此我不确定当我向上推scrollview时,它如何知道需要重建自身 我不想重建自己,因为没有理由它应该重建自己。它是静态/无状态的,根本不应该更改。收割台的尺寸也不应改变(因此展开高度和收拢高度在136.0处相同) 下面是我为您重新

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

我不想重建自己,因为没有理由它应该重建自己。它是静态/无状态的,根本不应该更改。收割台的尺寸也不应改变(因此展开高度和收拢高度在136.0处相同)

下面是我为您重新创建的示例代码:

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)),
          ]),
        ));
  }

}
import'package:meta/meta.dart';
进口“包装:颤振/材料.省道”;
进口“包装:颤振/cupertino.dart”;
导入'dart:math'作为数学;
导入“dart:async”;
类_TestHeader扩展SliverPersistentHeaderDelegate{
_测试头({
@需要此。折叠高度,
@需要此。展开高度,
@需要此。显示标题,
});
bool-showtheding;
最终双膨胀高度;
最终双折高度;
@凌驾
double get minExtent=>collapsedHeight;
@凌驾
double-get-maxExtent=>math.max(expandedHeight,minExtent);
@凌驾
小部件构建(
BuildContext上下文、双收缩偏移、布尔重叠内容){
打印(“重建标题”);
返回新的安全区域(
子项:列(子项:[
const SizedBox(高度:24.0),
新手势检测器(
onTap:(){
},
子容器:新容器(
装饰:康斯特盒子装饰(
颜色:铜色。白色,
边界:康斯特边界(
顶部:常量边界边(颜色:常量颜色(0xFFBCBBC1),宽度:0.0),
底部:
常量边界边(颜色:常量颜色(0xFFBCBBC1),宽度:0.0),
),
),
身高:44.0,
孩子:新的填充物(
衬垫:
常数边集对称(水平:16.0,垂直:8.0),
儿童:新安全区(
上图:错,
底部:错误,
孩子:新的一排(
mainAxisAlignment:mainAxisAlignment.center,
儿童:康斯特[
常量文本(
“这是我的标题”,
样式:const TextStyle(颜色:CupertinoColors.activeBlue,fontSize:16.0),
)
],
),
),
),
),
),
]));
}
@凌驾
bool shouldRebuild(@checked\u TestHeader oldDelegate){
//返回false;
返回expandedHeight!=oldDelegate.expandedHeight||
collapsedHeight!=oldDelegate.collapsedHeight;
}
}
类TestHeaderPage扩展StatefulWidget{
@凌驾
状态createState(){
//TODO:实现createState
返回新的TestHeaderState();
}
}
类TestHeaderState扩展状态{
@凌驾
小部件构建(构建上下文){
//TODO:实现构建
返回新的CupertinoPageScaffold(
//我需要将其转换为一个小片段列表,以使其正常工作。
背景颜色:常量颜色(0xFFEFFF4),
导航栏:新的CupertinaVigationBar(
中间:新文本(“测试标题”),
),
儿童:新安全区(
子项:新的CustomScrollView(片段:[
新的CupertinoRefreshControl(onRefresh:(){
打印(“刷新时拉动”);
返回未来((){});
}),
新型滑片导板(
代表:新的_TestHeader(
折叠高度:136.0,
扩展高度:136.0,
showtheading:true),
]),
));
}
}

这是完全正常的

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

您扩展了用于构建
SliverPersistentHeaderDelegate
SliverPersistentHeaderDelegate

问题是:
SliverPersistentHeader
也不是小部件。它是一条细条,这是一种在屏幕上渲染东西的不同方式

而且,在
SliverPersistentHeader
的情况下,它是一种特定类型的sliver,每当滚动偏移量改变时都会重新生成。也就是说,可以处理特定于滚动的动画。
例如向上滚动使标题消失。并向下滚动,使其快速回复

谢谢你的解释。我还注意到,我需要提供折叠和扩展高度的标题,但我只需要一个静态标题。如果我不提供折叠和扩展的高度,没有silver可以只渲染静态标题(固定的标题,大小不会改变)吗?您不需要将它们传递给
\u TestHeader
。您可以将它们从构造函数中删除,并将它们从harcode
minExtent
maxExtent
中删除到
136.0