SliverAppBar内容在滚动时消失

时间:2019-01-16 20:59:58

标签: dart flutter

AppBar重新设置动画时(滚动条到达顶部之后),SliverAppBar无法显示内容。

在下面包括一个示例项目来演示该问题。复制/粘贴下面的代码(将rxdart依赖项添加到pubspec.yaml中)并运行app。请注意,SliverAppBar包含一些来自流的文本(请参见下面的功能1和2)。现在向下滚动计数器列表,直到SliverAppBar消失。滚动备份以使AppBar重新显示,请注意现在有两个ProgressIndicators但没有文本。

要求一旦AppBar再次出现在视图中即可显示文本,理想情况下不必再次调用以下功能(这些实际上是实际应用中的api调用):

SliverAppBar内容功能

bloc.fetchTestAppBarTxt1();
bloc.fetchTestAppBarTxt2();

示例应用

void main() => runApp(TestApp());
class TestApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    TestBloc bloc = TestBloc();
    bloc.fetchTestTimeline();
    bloc.fetchTestAppBarTxt1();
    bloc.fetchTestAppBarTxt2();
    return MaterialApp(
      home: new Scaffold(
          backgroundColor: Colors.grey[200],
          appBar: AppBar(
            backgroundColor: Colors.blueGrey,
            elevation: 0.0,
          ),
          body: CustomScrollView(slivers: <Widget>[
            SliverAppBar(
                automaticallyImplyLeading: false,
                backgroundColor: Colors.grey[400],
                expandedHeight: 200.0,
                floating: true,
                snap: true,
                flexibleSpace: FlexibleSpaceBar(
                  background: Column(
                    children: <Widget>[
                      Container(
                        padding: EdgeInsets.only(left: 2.0),
                        height: 200,
                        child: Column(
                          children: <Widget>[
                            StreamBuilder(
                                stream: bloc.testAppBarTxt1,
                                initialData: null,
                                builder: (BuildContext context,
                                    AsyncSnapshot<String> snapshot) {
                                  if (snapshot.data == null)
                                    return buildProgressIndicator(true);
                                  return Expanded(
                                      child: Text('${snapshot.data}'));
                                }),
                            StreamBuilder(
                                stream: bloc.testAppBarTxt2,
                                initialData: null,
                                builder: (BuildContext context,
                                    AsyncSnapshot<String> snapshot) {
                                  if (snapshot.data == null)
                                    return buildProgressIndicator(true);
                                  return Expanded(
                                      child: Text('${snapshot.data}'));
                                }),
                          ],
                        ),
                      )
                    ],
                  ),
                )),
            timelineList(bloc)
          ])),
    );
  }
  Widget timelineList(TestBloc bloc) {
    return StreamBuilder(
        stream: bloc.getTestTimeline,
        initialData: null,
        builder: (BuildContext context, AsyncSnapshot<List<int>> snapshot) {
          List<int> val = snapshot.data;
          if (val == null)
            return SliverToBoxAdapter(child: buildProgressIndicator(true));
          if (val.isNotEmpty) {
            addToTimelineList(val, bloc);
            return SliverList(
                delegate: SliverChildListDelegate(new List<Widget>.generate(
                        bloc.listTest.length, (int index) {
              if (index == bloc.listTest.length) {
                return SliverToBoxAdapter(
                    child: buildProgressIndicator(bloc.isPerformingRequest));
              } else {
                return bloc.listTest[index];
              }
            })
                    ));
          }
        });
  }
  void addToTimelineList(List<int> list, TestBloc bloc) {
    for (var val in list) {
      bloc.listTest.add(Text('$val'));
    }
  }
}

class TestBloc {
  List<Text> listTest = new List<Text>();
  bool isPerformingRequest = false;
  final _testAppBarText1 = PublishSubject<String>();

  Observable<String> get testAppBarTxt1 => _testAppBarText1.stream;
  final _testAppBarText2 = PublishSubject<String>();

  Observable<String> get testAppBarTxt2 => _testAppBarText2.stream;
  final _testTimeline = PublishSubject<List<int>>();

  Observable<List<int>> get getTestTimeline => _testTimeline.stream;

  fetchTestTimeline() async {
    List item = await Future.delayed(
        Duration(seconds: 2), () => List<int>.generate(100, (i) => i));
    _testTimeline.sink.add(item);
  }

  fetchTestAppBarTxt1() async {
    String val = await Future.delayed(Duration(seconds: 2), () => "Text One");
    _testAppBarText1.sink.add(val);
  }

  fetchTestAppBarTxt2() async {
    String val = await Future.delayed(Duration(seconds: 2), () => "Text Two");
    _testAppBarText2.sink.add(val);
  }
  dispose() {
    _testAppBarText1.close();
    _testAppBarText2.close();
    _testTimeline.close();
  }
}

1 个答案:

答案 0 :(得分:0)

这是因为每次您再次隐藏并显示小部件时,内部的StreamBuilder都会等待数据,而您没有使用initialData。

要修复您的代码,您将必须使用BehaviorSubjectValueObservable,请检查以下修复程序:

          final _testAppBarText1 = BehaviorSubject<String>();
          ValueObservable<String> get testAppBarTxt1 => _testAppBarText1.stream;

          final _testAppBarText2 = BehaviorSubject<String>();
          ValueObservable<String> get testAppBarTxt2 => _testAppBarText2.stream;


                      StreamBuilder(
                            stream: bloc.testAppBarTxt1,
                            initialData: bloc.testAppBarTxt1.value,



                        StreamBuilder(
                            stream: bloc.testAppBarTxt2,
                            initialData: bloc.testAppBarTxt2.value,