Dn-a / flutter_inner_drawer

Inner Drawer is an easy way to create an internal side section (left/right) where you can insert a list-menu or other.
https://pub.dartlang.org/packages/flutter_inner_drawer
MIT License
516 stars 130 forks source link

Want swipe to close, but not to open #20

Open Skquark opened 4 years ago

Skquark commented 4 years ago

I love the effect when the menu is open to swipe to close, but I don't want my menu to open up when swiping from the side of scaffold. My interface already has a swipable tabview and pageview, so that doesn't work together, but I still want to close it with the swipe.. I tried to find a way, but couldn't figure it out unless I fork and mod, but didn't want to do that if I don't have to. Any suggestions? Otherwise this is a feature request.

Another side question I had, is there a way to shade a color overlay on the scaffold content? Thought it'd look cooler with the transition animation to darken the content as it moves to the side. Thanks, loving this drawer compared to all the other one's I've tried to use.. Much appreciated.

Dn-a commented 4 years ago

@Skquark thanks for the feedback :D 1) if I understand correctly you don't want to swipe it when it's closed, only when it's open. You could use a variable (eg: boolean swipe = false) to use to set the swipe field, and when the drawer is open, set it to true.

boolean swipe = false;
InnerDrawer(           
            swipe: swipe,
            innerDrawerCallback: (val) => swipe=val,
)

2) yes of course! one way could be to use a stack, example:

double transition = 0;
ColorTween  color = ColorTween(begin: Colors.transparent, end: Colors.black54);
InnerDrawer(
           onDragUpdate: (double val, InnerDrawerDirection direction) {
                transition = val;
            },           
           scaffold: Stack(
                    children: [
                        Scaffold(
                        appBar: AppBar(
                            automaticallyImplyLeading: false
                        ),
                        transition>0?
                        Container(
                            color: color.evaluate(transition),
                        ): null
                    ].where((a) => a != null).toList(),
               ) 
)

this is a solution but there may be more refined ways. let me know!

Skquark commented 4 years ago

That seemed like a nice elegant solution to toggle the swipe with menu opened/closed, but ran into a problem when I put that in place.. The innerDrawerCallback sets it to false when the drawer is swiped halfway closed, so after I put that swipe: swipable bool in, and I start to swipe the drawer closed, it gets stuck part way in the swiping closed. Played with it some more and found this method using onDragUpdate instead. First I declare double dragVal = 0.0; then inside my InnerDrawer(

        swipe: dragVal >= 0.01,
        onDragUpdate: (double val, InnerDrawerDirection direction) {
          setState(() => dragVal = val);
        }

Regarding the shading of the scaffold, I guess that suggestion of putting it in the stack would work, but seemed like just as much work putting it the component. After looking at the code, looked like it'd be more refined to add an overlayColor property and create a ColorTween controller that applies a ColorFiltered on the scaffold widget.. So I took some time to mod it, which was fairly fun.. Here's what I ended up with:

In the constructor, declare these:

  /// Color of the scaffold's cover overlay
  final Color overlayColor;

  /// The BlendMode of the overlay color filter (default: BlendMode.color)
  final BlendMode overlayBlend;

Top of InnerDrawerState:

  ColorTween _overlayColor =
      ColorTween(begin: Colors.black54, end: Colors.transparent);

Inside _animationChanged() {

    if (widget.overlayColor != null)
      _overlayColor = ColorTween(
          begin: widget.overlayColor,
          end: widget.overlayColor.withOpacity(0.0));

Then on the top of Widget _scaffold() {

    Widget scaffoldWidget = widget.scaffold;
    if (widget.overlayColor != null && _controller.value != 1.0)
      scaffoldWidget = ColorFiltered(
        colorFilter: ColorFilter.mode(_overlayColor.evaluate(_controller), widget.overlayBlend ?? BlendMode.color),
        child: scaffoldWidget,
      );

and then replace widget.scaffold with scaffoldWidget a little lower in:

        child: widget.borderRadius != 0
            ? ClipRRect(
                borderRadius: BorderRadius.circular(
                    (1 - _controller.value) * widget.borderRadius),
                child: scaffoldWidget,
              )
            : scaffoldWidget);

... Loos real nice to me now, so wanted to contribute that style for others. If you want I can put those changes in a fork and make a pull request, but it wasn't that difficult since Flutter is so flexible. Once again, thanks for a great component!

Dn-a commented 4 years ago

@Skquark 1) Returns false because until more than 50% is open, if you release it it closes automatically. your solution is more suitable for the context.

2) thanks for the advice! I have to release a new version soon, I can add this feature directly.