【问题标题】:How can I customise the flexibleSpace property in SliverAppBar in Flutter?Flutter中如何自定义SliverAppBar中的flexibleSpace属性?
【发布时间】:2019-05-26 12:14:32
【问题描述】:

我不想在 SliverAppBar 的 flexibleSpace 属性中使用 FlexibleSpaceBar,而是想使用自定义小部件树,在展开时,但在滚动时,我想显示自定义文本,而不是小部件树。

我创建了一个自定义小部件树,该树应分配给 flexibleSpace 属性,但我不知道如何在滚动时显示自定义文本,并隐藏小部件树。

SliverAppBar(
          expandedHeight: 180.0,
          backgroundColor: const Color(0xFF9e0118),
          iconTheme: IconThemeData(color: Colors.white),
          floating: true,
          pinned: true,
          flexibleSpace: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Container(
                  margin: EdgeInsets.only(top: 16.0),
                  padding: EdgeInsets.only(left: 32.0, right: 32.0),
                  child: Text(
                    'Some text',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        color: Colors.white,
                        fontFamily: 'PlayfairDisplay',
                        fontStyle: FontStyle.italic,
                        fontSize: 16.0),
                  )),
              Container(
                  margin: EdgeInsets.only(top: 16.0),
                  padding: EdgeInsets.only(left: 32.0, right: 32.0),
                  child: Text(
                    'some text',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        color: Colors.white,
                        fontFamily: 'PlayfairDisplay',
                        fontSize: 16.0),
                  )),
            ],
          ),
        ),

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    您可能希望将小部件树包装在 FlexibleSpaceBar 小部件中,并将小部件树添加为背景。我希望我理解你的问题是正确的。检查this gif

    SliverAppBar(
          expandedHeight: 180.0,
          backgroundColor: const Color(0xFF9e0118),
          iconTheme: IconThemeData(color: Colors.white),
          floating: true,
          pinned: true,
          flexibleSpace: FlexibleSpaceBar(
            collapseMode: CollapseMode.pin,
            centerTitle: true,
            background: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Container(
                    margin: EdgeInsets.only(top: 16.0),
                    padding: EdgeInsets.only(left: 32.0, right: 32.0),
                    child: Text(
                      'Some text',
                      textAlign: TextAlign.center,
                      style: TextStyle(
                          color: Colors.white,
                          fontFamily: 'PlayfairDisplay',
                          fontStyle: FontStyle.italic,
                          fontSize: 16.0),
                    )),
                Container(
                    margin: EdgeInsets.only(top: 16.0),
                    padding: EdgeInsets.only(left: 32.0, right: 32.0),
                    child: Text(
                      'some text',
                      textAlign: TextAlign.center,
                      style: TextStyle(
                          color: Colors.white,
                          fontFamily: 'PlayfairDisplay',
                          fontSize: 16.0),
                    )),
              ],
            ),
          ),
        ),
    

    【讨论】:

    • 谢谢。这解决了我的部分问题,即我可以在滚动时隐藏我的自定义小部件树。第二部分是我还希望能够在固定时在应用栏上显示一些文本,并且用户正在滚动,目前它只是空白的红色背景。
    • 嘿,我刚看到你的评论。如果还没有解决,让我想想给你答案。
    • 当然。请做。谢谢。
    【解决方案2】:

    要完成@westdabestdb 的回答,让标题出现在滚动条上,真的很简单。

    您只需要添加您选择的动画小部件并使用滚动控制器中的 addListener 来切换布尔值。要查找更多动画小部件,请访问 Flutter 动画小部件的官方文档:https://flutter.dev/docs/development/ui/widgets/animation

    这是一个带有 AnimatedOpacity 小部件和 Parallax 折叠模式的示例,在我看来它们可以很好地协同工作。

    class YourPage extends StatelessWidget {
      const YourPage({Key key}) : super(key: key);
    
      ScrollController _scrollController;
      bool _isScrolled = false;
    
      @override
      void initState() { 
        _scrollController = ScrollController();
        _scrollController.addListener(_listenToScrollChange);
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Scaffold(
            body: CustomScrollView(
              controller: _scrollController,
              slivers: <Widget>[
                SliverAppBar(
                  expandedHeight: 144.0,
                  pinned: true,
                  forceElevated: true,
                  ////////////////////////////////////
                  // HERE IS THE PART TO BE ADDED
                  title: AnimatedOpacity(
                    duration: Duration(milliseconds: 300),
                    opacity: _isScrolled ? 1.0 : 0.0,
                    curve: Curves.ease,
                    child: Text("YOUR TITLE HERE"),
                  ),
                  ////////////////////////////////////
                  flexibleSpace: FlexibleSpaceBar(
                    titlePadding: const EdgeInsets.only(bottom: 8.0),
                    centerTitle: true,
                    collapseMode: CollapseMode.parallax,
                    background: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        Container(
                            margin: EdgeInsets.only(top: 16.0),
                            padding: EdgeInsets.only(left: 32.0, right: 32.0),
                            child: Text(
                              'Some text',
                              textAlign: TextAlign.center,
                              style: TextStyle(
                                  color: Colors.white,
                                  fontFamily: 'PlayfairDisplay',
                                  fontStyle: FontStyle.italic,
                                  fontSize: 16.0),
                            )),
                        Container(
                            margin: EdgeInsets.only(top: 16.0),
                            padding: EdgeInsets.only(left: 32.0, right: 32.0),
                            child: Text(
                              'some text',
                              textAlign: TextAlign.center,
                              style: TextStyle(
                                  color: Colors.white,
                                  fontFamily: 'PlayfairDisplay',
                                  fontSize: 16.0),
                            )),
                      ],
                    ),
                  ),
                )
              ],
            ),
          ),
        );
      }
    
    // METHODS
      void _listenToScrollChange() {
        if (_scrollController.offset >= 48.0) {
          setState(() {
            _isScrolled = true;
          });
        } else {
          setState(() {
            _isScrolled = false;
          });
        }
      }
    }
    

    您只需要在 _listenToScrollChange 中使用 if 的值 以及动画的持续时间以获得所需的输出。

    【讨论】:

    • 我有一个类似的问题,当我尝试这个答案时,我确实得到了想要的输出,但是应用程序的 UI 变得非常滞后和缓慢。响应时间迅速减少。有解决办法吗?
    • 此方法过于频繁地在整个小部件树上调用 setState(),这肯定会使 UI 滞后。
    • 是的,这可能是对的,我没有亲自尝试过。要解决此问题,您可以做的是检查是否应该更改 _isScrolled,从而减少 setStates。只需将 if 更改为 this => if(_scrollController.offset >= 48.0 && !_isScrolled) 和 else if(_isScrolled)
    猜你喜欢
    • 2020-11-27
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    • 2020-02-25
    • 2021-02-05
    • 2020-09-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多