rodydavis / floating_search_bar

Floating Search Bar like Gmail for Flutter
https://rodydavis.github.io/floating_search_bar/
MIT License
32 stars 27 forks source link

[feature request] FloatingSearchBar - Top Padding #2

Closed gleesonger closed 4 years ago

gleesonger commented 5 years ago

The padding at the top of FloatingSearchBar should be configurable so that a small region can be inserted between the search bar and the top of the containder. I suggest a non-zero default of 12, consistent with the left/right padding.

File: sliver_search_bar.dart Location _SliverAppBarDelegate.build (line 347)

    final Widget appBar = FlexibleSpaceBar.createSettings(
      minExtent: minExtent,
      maxExtent: maxExtent,
      currentExtent: math.max(minExtent, maxExtent - shrinkOffset), 
      toolbarOpacity: toolbarOpacity,
      child: Container(
        padding: this.padding,       <---------------------------------------- Line updated, supplied by user
        child: SafeArea(
          child: Material(
            color: backgroundColor,
            borderRadius: BorderRadius.circular(8.0),
Screenshot_1562456466
vnlevanduoc commented 5 years ago

After fixing it like this, the interface is not nice anymore, can you share your code? padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 12) Screenshot_20190728-153511

gleesonger commented 5 years ago

Updated code below, I've marked up the lines which I changed. I've also attached the the files, however there are a few more changes in this code that just the padding: onSubmitted callback added and search icon shown in keyboard rather than enter, plus potentially anything else I've forgotten.

floating_search_bar.zip

sliver_search_bar.dart / SliverFloatingBar:

@override
  Widget build(BuildContext context) {
    final double topPadding = MediaQuery.of(context).padding.top + widget.padding.top; <-- Updated
    final double collapsedHeight =
        (widget.pinned && widget.floating) ? (topPadding+widget.padding.bottom) : null; <-- Updated

    return MediaQuery.removePadding(
      context: context,
      removeBottom: true,
      child: SliverPersistentHeader(
        floating: widget.floating,
        pinned: widget.pinned,
        delegate: _SliverAppBarDelegate(
          leading: widget.leading,
          automaticallyImplyLeading: widget.automaticallyImplyLeading,
          title: widget.title,
          trailing: widget.trailing,
          elevation: widget.elevation,
          backgroundColor: widget.backgroundColor,
          floating: widget.floating,
          pinned: widget.pinned,
          snapConfiguration: _snapConfiguration,
          collapsedHeight: collapsedHeight,
          padding: EdgeInsets.only(left: widget.padding.left, right: widget.padding.right, top: topPadding, bottom: widget.padding.bottom), <-- Updated
        ),
      ),
    );
  }

sliver_search_bar.dart / _SliverAppBarDelegate :

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  _SliverAppBarDelegate({
    @required this.leading,
    @required this.automaticallyImplyLeading,
    @required this.title,
    @required this.trailing,
    @required this.elevation,
    @required this.backgroundColor,
    @required this.floating,
    @required this.pinned,
    @required this.snapConfiguration,
    @required this.collapsedHeight,
    @required this.padding,  <-- Updated - renamed topPadding to just padding
  });

  final Widget trailing;
  final bool automaticallyImplyLeading;
  final Color backgroundColor;
  final double elevation;
  final bool floating;
  final Widget leading;
  final bool pinned;
  final Widget title;
  final double collapsedHeight;
  final EdgeInsets padding; <-------------- Updated type

  @override
  double get minExtent => collapsedHeight ?? (padding.vertical + kToolbarHeight);  <-- Updated

  @override
  final FloatingHeaderSnapConfiguration snapConfiguration;

  @override
  double get maxExtent => math.max(padding.vertical + kToolbarHeight, minExtent);   <-- Updated

  @override
  bool shouldRebuild(covariant _SliverAppBarDelegate oldDelegate) {
    return leading != oldDelegate.leading ||
        automaticallyImplyLeading != oldDelegate.automaticallyImplyLeading ||
        title != oldDelegate.title ||
        trailing != oldDelegate.trailing ||
        elevation != oldDelegate.elevation ||
        padding != oldDelegate.padding ||   <-- Updated
        collapsedHeight != oldDelegate.collapsedHeight ||
        backgroundColor != oldDelegate.backgroundColor ||
        pinned != oldDelegate.pinned ||
        floating != oldDelegate.floating ||
        snapConfiguration != oldDelegate.snapConfiguration;
  }

  @override
  String toString() {
    return '';
  }

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    final double visibleMainHeight = maxExtent - shrinkOffset;

    // // Truth table for `toolbarOpacity`:
    // // pinned | floating | bottom != null || opacity
    // // ----------------------------------------------
    // //    0   |    0     |        0       ||  fade
    // //    0   |    0     |        1       ||  fade
    // //    0   |    1     |        0       ||  fade
    // //    0   |    1     |        1       ||  fade
    // //    1   |    0     |        0       ||  1.0
    // //    1   |    0     |        1       ||  1.0
    // //    1   |    1     |        0       ||  1.0
    // //    1   |    1     |        1       ||  fade
    final double toolbarOpacity = !pinned || (floating)
        ? ((visibleMainHeight) / kToolbarHeight).clamp(0.0, 1.0)
        : 1.0;

    final Widget appBar = FlexibleSpaceBar.createSettings(
      minExtent: minExtent,
      maxExtent: maxExtent,
      currentExtent: math.max(minExtent, maxExtent - shrinkOffset),
      toolbarOpacity: toolbarOpacity,
      child: Container(
        padding: this.padding,    <-- Updated
        child: SafeArea(
          child: Column(   <-- Added this widget (not sure why, might be the left overs of some testing I was doing)
            children: <Widget>[
              Material(
                color: backgroundColor,
                borderRadius: BorderRadius.circular(8.0),
                elevation: elevation,
                child: ListTile(
                  leading: leading ??
                           (Scaffold.of(context).hasDrawer && automaticallyImplyLeading
                            ? IconButton(
                             icon: Icon(Icons.menu),
                             onPressed: () {
                               Scaffold.of(context).openDrawer();
                             },
                             )
                            : null),
                  title: title,
                  trailing: trailing ??
                            (Scaffold.of(context).hasEndDrawer &&
                             automaticallyImplyLeading
                             ? IconButton(
                              icon: Icon(Icons.menu),
                              onPressed: () {
                                Scaffold.of(context).openEndDrawer();
                              },
                              )
                             : null),
                  ),
                ),
            ],
          )
        ),
      ),
    );
    return Container(child: floating ? _FloatingAppBar(child: appBar) : appBar);
  }
}
rodydavis commented 5 years ago

Can you submit a PR? Ill push an update

github-actions[bot] commented 4 years ago

This issue has been closed due to inactivity.

rodydavis commented 4 years ago

Fixed on latest version