繁体   English   中英

flutter - 如何让我的应用栏在灵活的应用栏的同时充当材料搜索小部件

[英]flutter - How can I make my appbar act as material search widget while being flexible app bar

我希望我的 appbar 在向下滚动或用户搜索某些内容时充当固定的 appbar。

SliverAppBar(
  title: new TextField(
    style: Theme.of(context).primaryTextTheme.title,
    decoration: InputDecoration(
      hintText: '검색',
    ),
  ),
),

搜索


但是当它向上滚动并且用户没有搜索时,我想将它绘制为一个灵活的应用程序栏。

flexibleSpace: new FlexibleSpaceBar(
  centerTitle: false,
  title: new TextField(
    style: Theme.of(context).primaryTextTheme.title,
    decoration: InputDecoration(
      hintText: '검색',
    ),
  ),
  background: Stack(
    fit: StackFit.expand,
    children: <Widget>[
      SizedBox(
        height: 256.0,
        child: Container(
          child: Padding(
            padding: const EdgeInsets.only(top: 24.0),
            child: Column(
              children: <Widget>[
                Align(
                  alignment: Alignment.topLeft,
                  child: FlutterLogo(
                    size: 64.0,
                  ),
                ),
                Padding(padding: const EdgeInsets.only(bottom: 24.0)),
                ListTile(
                  title: Text('Some Text'),
                ),
              ],
            ),
          ),
        ),
      ),
      // This gradient ensures that the toolbar icons are distinct
      // against the background image.
    ],
  ),
),

向上滚动

使用第二种方法向上滚动时,搜索字段会转换到右上角。

该效果可以通过将标题内容移动到另一个 SliverList 来实现。

从 SliverAppBar 中移除flexibleSpace ,并将 flexibleSpace.background 的内容移动到 SliverAppBar之前的 SliverList。

例子:

@override
Widget build(BuildContext context) {
  return new CustomScrollView(
    slivers: <Widget>[
      new SliverList(
          delegate: new SliverChildListDelegate(<Widget>[
        Align(
          alignment: Alignment.topLeft,
          child: FlutterLogo(size: 64.0),
        ),
        ListTile(
          title: Text('Some Text'),
        ),
        ListTile(),
      ])),
      new SliverAppBar(
        backgroundColor: Theme.of(context).scaffoldBackgroundColor,
        elevation: 0.0,
        automaticallyImplyLeading: false,
        pinned: true,
        floating: false,
        title: new TextField(
          focusNode: _searchFocusNode,
          style: Theme.of(context).primaryTextTheme.title,
          decoration: InputDecoration(
            border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
            suffixIcon: Icon(Icons.search),
            hintText: '검색',
          ),
        ),
      ),
      new SliverList(
        delegate: new SliverChildListDelegate(List.generate(
            100,
            (i) => ListTile(
                  title: Text('Scroll'),
                )).toList()),
      ),
    ],
  );
}

我写了一个getMaterialSerach(); 要点中的方法具有您需要的确切材料搜索视图。 只需在您的appBar:小部件中添加 getMaterialSearch(),如下所示。 这是 getMaterialSearch() 的要点;

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: getMaterialSearchBar(),
      body: Center(
        child: Container(),
      ),
    );
  }

这是我在 SliverAppBar 中带有 TextField 和 Tabs 的代码:

在此处输入图片说明

NestedScrollView(
                    controller: model.mainScrollController,
                    headerSliverBuilder: (context, innerBoxIsScrolled) {
                      return [
                        /// https://github.com/flutter/flutter/issues/54059
                        SliverOverlapAbsorber(
                          handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                          sliver: SliverAppBar(
                            automaticallyImplyLeading: false,
                            pinned: true,
                            floating: true,
                            snap: true,
                            expandedHeight: 100,
                            flexibleSpace: FlexibleSpaceBar(
                              collapseMode: CollapseMode.pin,
                              background: Padding(
                                padding: const EdgeInsets.symmetric(vertical: 16.0),
                                child: Row(
                                  children: [
                                    BackButton(
                                      color: Colors.white,
                                    ),
                                    Flexible(
                                      child: TextField(
                                        controller: model.searchController,
                                        decoration: InputDecoration(
                                            focusColor: Colors.blueAccent,
                                            hoverColor: Colors.blueAccent,
                                            fillColor: Colors.white,
                                            filled: true,
                                            isDense: true,
                                            prefixIconConstraints: BoxConstraints(maxHeight: 24, maxWidth: 48),
                                            prefixIcon: Padding(
                                              padding: const EdgeInsets.symmetric(horizontal: 8.0),
                                              child: Icon(Icons.search_outlined),
                                            ),
                                            hintText: 'Search...'),
                                      ),
                                    ),
                                    IconButton(
                                      icon: Icon(
                                        Icons.add,
                                        color: Colors.white,
                                      ),
                                      onPressed: () {
                                        ExtendedNavigator.named('topNav').push(Routes.newExerciseView);
                                      },
                                      tooltip: 'Create Exercise',
                                    ),
                                  ],
                                ),
                              ),
                            ),
                            bottom: TabBar(
                              labelPadding: EdgeInsets.only(bottom: 8),
                              indicatorWeight: 3,
                              indicatorSize: TabBarIndicatorSize.label,
                              tabs: [
                                Text('All'),
                                Text('Custom'),
                                Text('Favorites'),
                              ],
                            ),
                          ),
                        ),
                      ];
                    },
                    body: TabBarView(
                        children: [
                      AllExercises(),
                      CustomExercises(),
                      FavoriteExercises(),
                    ]),
                  ),

有几个关键部分可以使这项工作正常进行,首先是您需要使用 SliverAppBar 的flexibleSpace属性来添加您的搜索小部件。 如果您尝试将其添加到 title 属性中,则 TextField 只会被压扁但永远不会离开屏幕。

其次,确保 FlexibleSpaceBar 的 collapseMode 设置为CollapseMode.pin 这使得 flexibleSpace 的内容滚动到屏幕外并且不会改变大小。

最后,将 sliverAppBar 上的 pinned 设置为 true,以便 TabBar 保持不变。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM