【问题标题】:Flutter: How to use RefreshIndicator with SliverAppBarFlutter:如何将 RefreshIndicator 与 SliverAppBar 一起使用
【发布时间】:2018-09-26 11:47:18
【问题描述】:

我正在尝试将RefreshIndicator 添加到CustomScrollView。有可能吗?这是代码示例:

CustomScrollView(
  slivers: <Widget>[
    SliverAppBar(
      title: Text('POSTAPP'),
      centerTitle: true,
      floating: true,
      pinned: false,
    ),
    SliverList(
        delegate: SliverChildBuilderDelegate(
          _createPostItem,
          childCount: postRepo.posts.length,
      ),
    ),
  ],
);

【问题讨论】:

  • 您是否尝试将您的CustomScrollView 放在RefreshIndicator 中?
  • 是的,但在这种情况下,刷新指示器将包裹整个内容,包括应用栏和列表视图,我想将它定位在 appBar 和列表视图之间
  • 我遇到了同样的问题,你能找到解决这种情况的方法吗?我无法在当前设置中使用 NestedScrollView。
  • 查看 Andrey Turkovsky 的回答 stackoverflow.com/a/52518878/8153664
  • 面临同样的问题。我不想更新 SliverAppBar。

标签: android ios dart flutter


【解决方案1】:

如果您不必限制使用CustomScrollView,您可以使用NestedScrollView 实现您的要求:

@override
Widget build(BuildContext context) {
  return NestedScrollView(
    headerSliverBuilder: (context, innerBoxScrolled) => [
          SliverAppBar(
            title: Text('POSTAPP'),
            centerTitle: true,
            floating: true,
            pinned: false,
          ),
        ],
    body: RefreshIndicator(
      onRefresh: _loadMorePosts,
      child: ListView.builder(
        itemBuilder: _createPostItem,
        itemCount: _postsCount,
      ),
    ),
  );
}

【讨论】:

  • 我试过这个,它似乎可以防止应用栏显示/隐藏滚动行为。什么可能导致这种情况发生?
  • @SacWebDeveloper 遇到了同样的问题,但只有一个“可扩展的”SliverAppBar(里面有FlexibleSpaceBar())。
【解决方案2】:

对于任何回过头来回答这个问题的人,我找到了一个使用包pull_to_refresh 的解决方案。

final RefreshController _refreshController = RefreshController();

Future<void> _onRefresh() async {
  await Future<void>.delayed(const Duration(milliseconds: 1000));
  _refreshController.refreshCompleted();
}

@override
Widget build(BuildContext context) {
  return CustomScrollView(
    slivers: [
      SliverAppBar(
        title: Text('Title'),
        centerTitle: true,
        floating: true,
        pinned: false,
      ),
      SliverFillRemaining(
        child: SmartRefresher(
          controller: _refreshController,
          onRefresh: _onRefresh,
          // ListView, CustomScrollView, etc. here
          child: SingleChildScrollView(
            child: Column(
              children: [
                Container(
                  height: 200,
                  color: Colors.red,
                ),
                Container(
                  height: 200,
                  color: Colors.blue,
                ),
                Container(
                  height: 200,
                  color: Colors.yellow,
                ),
              ],
            ),
          ),
        ),
      ),
    ],
  );
}

【讨论】:

    【解决方案3】:

    只有这样:

    RefreshIndicator(child: CustomScrollView(
            slivers: <Widget>[
              SliverAppBar(
                title: Text('POSTAPP'),
                centerTitle: true,
                floating: true,
                pinned: false,
              ),
              SliverList(
                  delegate: SliverChildBuilderDelegate(_createPostItem,
                      childCount: postRepo.posts.length))
            ],
          ), onRefresh: () => Future.value(true));
    

    SliverList 不可滚动,因此不能将其包装在 RefreshIndicator 中

    【讨论】:

    • 是否有任何选项可以在 SliverAppBar 和 SliverList 之间定位 RefreshIndicator ?
    • RefreshIndicator(displacement: ...) - 默认置换 = 40.0。您可以将其设置为与 SliverAppBar 的扩展高度相同,它将准确显示在 appbar 下方。附:但它会通过appbar从上到下滑动
    • 我需要让它出现在应用栏下
    • 怕你做不到
    • @RobertApikyan 您可以尝试使用 CupertinoSliverRefreshControl() 并修改其构建方法以根据需要显示您的自定义 refreshIndicator。快乐编码?示例:gist.github.com/RabiRoshan/6ac289c26c2c726b145a69fa521e3c3d
    【解决方案4】:

    我设法通过创建一个来自 flutter/lib/src/material/refresh_indicator.dart 的自定义小部件来实现。并修改以下代码(ps我只添加了变量initialDisplacement

    double initialDisplacement = 100.0;
    return Stack(
      children: <Widget>[
        child,
        if (_mode != null) Positioned(
          top: _isIndicatorAtTop ? initialDisplacement : null,
          bottom: !_isIndicatorAtTop ? 0.0 : null,
          left: 0.0,
          right: 0.0,
          child: SizeTransition(
            axisAlignment: _isIndicatorAtTop ? 1.0 : -1.0,
            sizeFactor: _positionFactor, // this is what brings it down
            child: Container(
              padding: _isIndicatorAtTop
                ? EdgeInsets.only(top: widget.displacement)
                : EdgeInsets.only(bottom: widget.displacement),
              alignment: _isIndicatorAtTop
                ? Alignment.topCenter
                : Alignment.bottomCenter,
              child: ScaleTransition(
                scale: _scaleFactor,
                child: AnimatedBuilder(
                  animation: _positionController,
                  builder: (BuildContext context, Widget child) {
                    return RefreshProgressIndicator(
                      semanticsLabel: widget.semanticsLabel ?? MaterialLocalizations.of(context).refreshIndicatorSemanticLabel,
                      semanticsValue: widget.semanticsValue,
                      value: showIndeterminateIndicator ? null : _value.value,
                      valueColor: _valueColor,
                      backgroundColor: widget.backgroundColor,
                      strokeWidth: widget.strokeWidth,
                    );
                  },
                ),
              ),
            ),
          ),
        ),
      ],
    );
    

    【讨论】:

      猜你喜欢
      • 2022-01-18
      • 2021-10-06
      • 1970-01-01
      • 2018-12-21
      • 2020-03-09
      • 1970-01-01
      • 2021-10-20
      • 1970-01-01
      • 2018-01-17
      相关资源
      最近更新 更多