Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a SlidableController #6

Closed
letsar opened this issue Jul 22, 2018 · 21 comments
Closed

Add a SlidableController #6

letsar opened this issue Jul 22, 2018 · 21 comments
Assignees
Labels
enhancement New feature or request

Comments

@letsar
Copy link
Owner

letsar commented Jul 22, 2018

A SlidableController could open/close any Slidable.
This can be useful if we want to close Slidables while scrolling, or if we want to close all the other Slidables while opening one.

@letsar
Copy link
Owner Author

letsar commented Jul 23, 2018

This is maybe not the right solution, because we'll have to maintain a list of Slidables or Keys and this could lead to potential issues, or complexity.
To open/close a Slidable based on a parent widget state we could have a boolean value to indicate the initial state.
For a slide action, we could create an of method to get the state and add open/close methods on the state.

@rhwoodpecker
Copy link

If this slide action is open, when I click on this item or other item, the slide action will be closed. When we click, we can traverse the other slide actions according to the keys.

@letsar
Copy link
Owner Author

letsar commented Jul 23, 2018

With the 0.3.0, I don't think we need a SlidableController now.

@hjJunior
Copy link

I'm trying to open when user clicks on child context, for more exacty when ListTile onTap event, so I stucked because I tried all of these two methods, and of these, before I got the call to function I got null

  slidableController.activeState?.open();
  Slidable.of(context)?.close();

@letsar
Copy link
Owner Author

letsar commented Aug 26, 2018

Hi @hjJunior,
The activeState property is null until a Slidable has been slid. This is why you can't use it in the onTap callback of the ListTile.
For the Slidable.of, it's probably because the ListTile is created under the same context than the Slidable. You need to create the ListTile under a Builder widget to provide a new scope with a BuildContext that is "under" the Slidable.

Widget build(BuildContext context) => Slidable(
    delegate: new SlidableDrawerDelegate(),
    actionExtentRatio: 0.25,
    closeOnScroll: false,
    controller: slidableController,
    child: new Builder(builder:  buildChild),
    actions: <Widget>[
      new IconSlideAction(
        caption: 'Archive',
        color: Colors.blue,
        icon: Icons.archive,
        onTap: () => print('Archive'),
      ),
      new IconSlideAction(
        caption: 'Share',
        color: Colors.indigo,
        icon: Icons.share,
        onTap: () => print('Share'),
      ),
    ]
  );

But I didn't design the animation to be programmatically called, so you will probably have an unexpected behavior.

@hjJunior
Copy link

I have tried but keeps returning null :(

    Widget build(BuildContext context) =>Slidable(
        delegate: new SlidableDrawerDelegate(),
        actionExtentRatio: 0.25,
        controller: slidableController,
        child: Builder(builder: (context) => _SlidableChild(widget.produtoPedido)),
        secondaryActions: <Widget>[
          ...
        ]
    );

And the child

class _SlidableChild extends StatelessWidget {
  final ProdutoPedido produtoPedido;
  _SlidableChild(this.produtoPedido);

  @override
  Widget build(BuildContext context) => ListTile(
    onTap: () {
      Slidable.of(context)?.open();
    },
    leading: (produtoPedido.pago) ? Icon(Icons.check_circle, color: Colors.green,) : null,
    title: Text('1x ${produtoPedido.produto.nome}'),
    subtitle: Text(produtoPedido.showDetalhes),
    trailing: Text(produtoPedido.valorFormatado),
  );
}

@letsar
Copy link
Owner Author

letsar commented Aug 28, 2018

@hjJunior can you please, paste the minimal code to reproduce this? Because I tested it with a function or a another widget like you, want under a Builder, the Slidable.of(context) is not null 😕

@tidharnitzan
Copy link

hi, it doesn't seem to work.
while I defined it correctly in the ctor I can still open several items and they all remain opened (I expected the other to auto close when another one is opened).
image

code:
...
final SlidableController slidableController = new SlidableController();
...
child: Slidable(
key: Key(_row.animalID),
controller: slidableController,
delegate: new SlidableBehindDelegate(),
actionExtentRatio: 0.25,
secondaryActions: [

....

@pushpendraKh
Copy link

@tidharnitzan Did it solve? I am also facing the same problem.

@tidharnitzan
Copy link

Not AFAIK. Still waiting for a response from developer for the code snippet above.

@pushpendraKh
Copy link

pushpendraKh commented Mar 22, 2019

It's working in this code https://pub.dartlang.org/packages/flutter_slidable#-example-tab-
May be we are doing something wrong.

@pushpendraKh
Copy link

@tidharnitzan I got the problem.
You should not create new instance of slidableController.
You are doing this inside cell, hence ending up creating new instance of controller everytime.

Instead, create slidableController in the controller itself and pass it to the cell and use it.
It will work.

@tidharnitzan
Copy link

@pushpendraKh - You are right! I'm still new to Flutter and totally missed that. all working great. thanks. !

@jawad12345A
Copy link

any luck

@adnankhan74444
Copy link

I need one Help I am using PopUpMenu in Slidable i want to close the slide when ever use clicks on PopupMenu item.
Slidable(
closeOnScroll: true,
key: Key(task.taskId),
controller: slidableController,
actionPane: SlidableScrollActionPane(),
actionExtentRatio: 0.2,
actions: [
//////////////// This is an PopUp///////////////////
PopupMenuButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
initialValue: selectedTaskStatus,
onSelected: (TaskStatus value) {
Slidable.of(context)?.close();
setState(() {
///////////////// I want to close the slide when onSelect Call///////////////////
selectedTaskStatus = value;
task.taskStatus = value.taskStatus;
_updateTask(context, task, viewModel);
});
},
child: IconSlideAction(
closeOnTap: false,
icon: Icons.playlist_add_check,
color: AppColors.swipe_geen,
caption: AppStrings.STATUS_LBL,
foregroundColor: AppColors.pureWhite,
),
itemBuilder: (BuildContext context) {
return getStatus.map((TaskStatus taskStatus) {
return PopupMenuItem(
value: taskStatus,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
],
),
],
));
}).toList();
},
),
],
);

@Mohammadwabeel
Copy link

Add this onTap() and call a separated widget in child property of Slidable and don't write child inside Slidable wid.

onTap: () {
Slidable.of(context).open();
},
//===================== Slidable Widget
Slidable(
controller: controller,
actionExtentRatio: 0.35,
actionPane: SlidableDrawerActionPane(),
actions: [
// Some Widget
],
secondaryActions: [
// Some Widget
],
child: Temps (),
);

//========= This is child in Slidable
class Temps extends StatefulWidget {
@OverRide
_TempsState createState() => _TempsState();
}

class _TempsState extends State {
@OverRide
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print(Slidable.of(context));
Slidable.of(context).open();
},
child: Container(
color: Colors.white,
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.amber,
child: Text("'{item.index}'"),
foregroundColor: Colors.white,
),
title: Text("item.title"),
subtitle: Text("item.subtitle"),
),
),
);
}

@saigopin
Copy link

@tidharnitzan I got the problem.
You should not create new instance of slidableController.
You are doing this inside cell, hence ending up creating new instance of controller everytime.

Instead, create slidableController in the controller itself and pass it to the cell and use it.
It will work.

It worked for me <3

@BrianDevOK
Copy link

I'm having trouble getting the slidableController initialised. Looks to require a vsync param. I've done that with various animation controllers, but stuck here. Can someone give an example.

I need to get the slidable to close when I swipe a different slidable, and need it to close when I tap a different slidable. Once I can get the slidableController initialised, I think I can take it from there. Thanks

@pushpendraKh
Copy link

pushpendraKh commented Dec 17, 2021

@BrianDevOK In latest version, SlidableController is not exposed and is meant to use internally.

So, you can wrap your ListView in SlidableAutoCloseBehavior which will close other Slidable.

@BrianDevOK
Copy link

Thanks... I had tried the SlidableAutoCloseBehavior but not around the ListView. That took care of closing when swiping another item.

How do I close it in this example: Swipe list item 1. Then tap on list item 2

In this example, my tap on list item 2 takes me to another view and when I hit back to my list, list item 1 is still open/slid.

Thanks

@pushpendraKh
Copy link

pushpendraKh commented Dec 17, 2021

@BrianDevOK You are right. Currently, v1.1.0 does not solve this but the next version will definitely solve this automatically as the required change is already pushed in master branch here

You can test the same in example project by running main_demo.dart

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

10 participants