flutter_slidable icon indicating copy to clipboard operation
flutter_slidable copied to clipboard

Action pane with rounded corners

Open amitkot opened this issue 3 years ago • 10 comments

I have Cards that are wrapped with Slidable widgets.

What I want

When the cards slide I want the action pane corners to be rounded as the Card:

Screen Shot 2020-10-29 at 11 25 18

(From material design documentation, specifically this video)

What I tried

Wrapping the action pane (SlidableBehindActionPane in this case) with ClipRRect.

What happened

the behaviour is inconsistent. Initially, the child is also clipped, but after sliding and sliding back the child is no longer clipped.

amitkot avatar Oct 29 '20 09:10 amitkot

Ok I will look at it for while doing the refactoring.

letsar avatar Nov 08 '20 21:11 letsar

I was able to accomplish this by wrapping the Action in an OverflowBox w/LayoutBuilder:

                                LayoutBuilder(
                                  builder: (context, constraints) =>
                                      OverflowBox(
                                    alignment: Alignment.topLeft,
                                    minWidth: constraints.minWidth,
                                    maxWidth: constraints.maxWidth + 10.0, // your corner radius
                                    minHeight: constraints.minHeight,
                                    maxHeight: constraints.maxHeight,
                                    child: IconSlideAction(
                                      caption: 'Archive',
                                      color: Colors.blue,
                                      icon: Icons.archive,
                                      onTap: () {},
                                    ),
                                  ),
                                ),

hope this helps!

denisbabineau avatar Dec 10 '20 19:12 denisbabineau

I was able to accomplish this by wrapping the Action in an OverflowBox w/LayoutBuilder:

                                LayoutBuilder(
                                  builder: (context, constraints) =>
                                      OverflowBox(
                                    alignment: Alignment.topLeft,
                                    minWidth: constraints.minWidth,
                                    maxWidth: constraints.maxWidth + 10.0, // your corner radius
                                    minHeight: constraints.minHeight,
                                    maxHeight: constraints.maxHeight,
                                    child: IconSlideAction(
                                      caption: 'Archive',
                                      color: Colors.blue,
                                      icon: Icons.archive,
                                      onTap: () {},
                                    ),
                                  ),
                                ),

hope this helps!

Hello this works for me too, but my requirement is opposite to OP's, which is set the actions card and my card has same borderRadius, like email app in iPadOS: image Is it possible to do this with your method? Thank you

Heheovereggs avatar Apr 05 '21 18:04 Heheovereggs

Should be ok with 1.0. Can you test it?

letsar avatar Jul 18 '21 08:07 letsar

I tried 1.0-dev.9. to add space and rounded corners to the actions.

First Problem: If the backgroundColor of SlideableAction is used, the whole available space is used and no space or rounded corners are appliable (At least I don't know how). So I tried it with CustomSlidableAction (following code):

            CustomSlidableAction(
              backgroundColor: Colors.blue,
              onPressed: (context) { },
              child: LayoutBuilder(
                builder: (context, constraints) => Container(
                  color: Colors.grey,
                  margin: EdgeInsets.symmetric(vertical: 4.0),
                  width: constraints.maxWidth,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      Icon(Icons.check_box_outline_blank),
                      Text("Remove")
                    ],
                  ),
                ),
              ),
            ),

Problem: but I'm not able to expand the Container horizontally. I would like the grey to be expanded horizontally, but it's tight with the Column's content (see following Screenshot). grafik

Question: How can I expand a child in CustomSlidableAction to the available space?

bernhardfrenking avatar Aug 29 '21 09:08 bernhardfrenking

This solution doesn't work any more

Should be ok with 1.0. Can you test it?

abigotado avatar Dec 17 '21 14:12 abigotado

There is a borderRadius on the SlidableAction now, can you test with the latest version?

letsar avatar Jul 10 '22 13:07 letsar

@letsar I am not sure this is enough, if you take a look at his screenshot, it has the radius to the opposite side. I am having the same problem, let me try to explain the way I see the problem and how I would solve it, maybe you know a easier way to solve. in the list, the item would have no radius, but, on the action of sliding, it would change that radius. With this new radius during the slide action, the item would be cropped, and the background from the start/end action would be visible. Now, I am not sure how things work under the hood, but, it would only be possible if the Slidable widget could be a container under the widget it is receiving, that could detect the color from the closest action of each ActionPanel and paint the half left and the half right of its own (under received Widget) container of the closest action Foreground colors. Also, it would be necessary that each panel could receive a callback, so we can identify when the sliding action is happening. (by the way, this callback would be awesome for multiple other things.) Does it make sense?

JeanPSF avatar Jul 27 '22 10:07 JeanPSF

Hi, I also made my own attempt, but IT ONLY WORKS BY ADDING clipBehavior: Clip.none, on the ClipRect() of the action pane (slidable.dart, line 244).

ActionPane(
  motion: const BehindMotion(),
  extentRatio: 0.25,
  children: [
    Expanded(
      child: LayoutBuilder(builder: (context, constraints) {
        return OverflowBox(
          alignment: Alignment.centerLeft,
          maxWidth: constraints.maxWidth + 15,
          child: GestureDetector(
            onTap: () {},
            child: Container(
              padding: const EdgeInsets.only(right: 15),
              decoration: const BoxDecoration(
                borderRadius: BorderRadius.horizontal(left: Radius.circular(15)),
                color: Colors.blue,
              ),
              alignment: Alignment.center,
              child: const Icon(Icons.copy, color: Colors.white),
            ),
          ),
        );
      }),
    ),
  ],
)

remi-martin avatar Oct 16 '22 12:10 remi-martin

Did it by overflowing the Slidable content width by its own borderRadius:

LayoutBuilder(builder: (context, constraints) {
  return Slidable(
    startActionPane: _buildStartActionPane,
    endActionPane: _buildEndActionPane,
    child: OverflowBox(
      alignment: Alignment.center,  // Alignment.center for both sides (Alignment.centerRight for startActionPane only and Alignment.centerLeft for endActionPane only)
      maxWidth: constraints.maxWidth + 30,  // 2 times the borderRadius for left and right
      child: Container(
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(15),
          color: Colors.white,
          boxShadow: const [
            BoxShadow(
              color: Colors.black26,
              blurRadius: 3,
              offset: Offset(1, 3),
            ),
          ],
        ),
        child: _content,
      ),
    ),
  );
})

The only issue is that the ActionPanes will have a margin equal to the border radius

remi-martin avatar Oct 17 '22 08:10 remi-martin