简体   繁体   中英

How to fix this dismissible widget border

I have a problem with a dismissible border which is marked on the screenshot

https://imgur.com/a/Jv0sdi2

return Dismissible(
    child: Container(
        height: 256,
        decoration: ShapeDecoration(
            shape: RoundedRectangleBorder(
                borderRadius: new BorderRadius.circular(20.0)
            )
        )
    );
);

I've encountered the same problem when I was trying to have rounded corners.

Eventually a little workaround did the trick.

Instead of having a background in the Dismissible , create a Stack and put the background widget behind the Dismissible

Stack(
  overflow: Overflow.clip,
  children: <Widget>[
    MyBackgroundWidget(), // instead of background
    Dismissible(
      child: MyForegroundWidget(),
      // no background
    )
  ],
);

The problem is the clipping behavior in dismissible.dart. I've managed to solve the problem by editing the Dismissible class itself. In lines 559 - 573, you will find an if-statement that looks like this:

if (background != null) {
      content = Stack(children: <Widget>[
        if (!_moveAnimation.isDismissed)
          Positioned.fill(
            child: ClipRect(
              clipper: _DismissibleClipper(
                axis: _directionIsXAxis ? Axis.horizontal : Axis.vertical,
                moveAnimation: _moveAnimation,
              ),
              child: background,
            ),
          ),
        content,
      ]);
    }

If you just comment out the clipper-property in ClipRect, the background will be transparent and you won't lose the collapsing animation.

I found a solution. Wrap Dismissible widget with ClipRRect widget, and remove borderRadius from, child widgets. Only ClipRRect should have borderRadius.

ClipRRect(
  borderRadius: BorderRadius.circular(15.0),
  child: Dismissible(
    child: YourWidgetContainer();
 )
)

在此处输入图片说明

That will not work because you are giving border to the whole Container instead, you should you BorderRadius.only

  return Dismissible(
  key: UniqueKey(),
  child: Container(
    height: 256,
    decoration: ShapeDecoration(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
            topLeft: Radius.circular(20),
            bottomLeft: Radius.circular(20.0)),
      ),
    ),
  ),
);

Now you can specifically choose to which side you want provide border.

I also faced the same problem and the best solution I found with a lot of customization is the following package: flutter_slidable . The link will navigate you to the options it provides. I love that!

As a workaround you could try to use this approach:

  1. Wrap your Dismissible with ClipRRect and give it some appropriate borderRadius, as the child of your Dismissible
  2. The wrap you child of your Dismissible in an extra Container and give it a LinearGradient for color from left to right with the colors of the two backgrounds of the Dismissible.

Check out this example on DartPad using the workaround: https://dartpad.dev/7224dd055bc7bdc73ab6eb66002db104

I do still see some issues that could arise, depending on what is inside of the backgrounds of the Dismissible but this should work in most cases.

Workaround example

it's 2021 and still there's no any solid fix that I've found regarding this issue.

So I was able to remove the ClipRect whenever the child of the Dismissiable widget is moving by modifying the Dismissiable widget package and add a Listener to the AnimationController to check if the child is actually moving . and I'm quit happy with the result .

you can do this by:

First:

open the Dismissable widget and define a clipBackground boolean and then right before the line 616 when it say's if (background != null) you should add this code :

    // Adding a Listener
    _moveAnimation.addListener(() {
      if (_moveController!.isDismissed) {
        setState(() {
          clipBackground = true;
        });
      }
      if (_moveController!.isCompleted) {
        setState(() {
          clipBackground = true;
        });
      }
      // if child stop moving
      if (_moveController!.value == 0) {
        setState(() {
          clipBackground = true;
        });
      }
      //If child is moving
      if (_moveController!.value != 0) {
        setState(() {
          clipBackground = false;
        });
      }
    });

Surely you can use the OR operator || to make code shorter.

Second:

modify the code where it say's if (background != null) and add a ternary operator so it will look like this :

if (background != null) {
      content = Stack(children: <Widget>[
        if (!_moveAnimation.isDismissed)
          Positioned.fill(
            child: ClipRect(
              //If true add a ClipRect to the widget
              clipper: clipBackground!
                  ? _DismissibleClipper(
                      axis: _directionIsXAxis ? Axis.horizontal : Axis.vertical,
                      moveAnimation: _moveAnimation,
                    )
                  : null,
              child: background,
            ),
          ),
        content,
      ]);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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