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

Extend slidable to perform action but not dismiss #318

Closed
nicolasvahidzein opened this issue Mar 14, 2022 · 9 comments
Closed

Extend slidable to perform action but not dismiss #318

nicolasvahidzein opened this issue Mar 14, 2022 · 9 comments

Comments

@nicolasvahidzein
Copy link

First off, THANK YOU. You did some AMAZING improvements to the package and on behalf of the entire community thank you!

I wanted to ask if it is possible to have a slidable element extend as if it was dismissable but not get rid of the item in question just trigger the action like we do on whatsapp to archive or mark a conversation as unread by swiping left or right to the edge of the tile?

Basically like a dismissable but no dismiss. I hope i was clear in my remarks.

Cheers.

@HammadBukhari
Copy link

For your use case, you can return false from confirmDismiss parameter of DismissiblePane and perform you desired action in it like

ActionPane(
      dragDismissible: true,
      dismissible: DismissiblePane(
        closeOnCancel: true,
        dismissThreshold: 0.9,
        confirmDismiss: () async {
          // always returning false so it doesn't get dismissed
          return false;
        },
        onDismissed: (){
           // perform your action here 
        },
      ),
)

@nicolasvahidzein
Copy link
Author

Thank you kind sir!!!!

@nicolasvahidzein
Copy link
Author

I do have one question though, the animation is broken though when we dismiss it and return false, it should close the drawer smoothly no?

@nicolasvahidzein
Copy link
Author

I opened a new issue, thanks.

@luis901101
Copy link

For your use case, you can return false from confirmDismiss parameter of DismissiblePane and perform you desired action in it like

ActionPane(
      dragDismissible: true,
      dismissible: DismissiblePane(
        closeOnCancel: true,
        dismissThreshold: 0.9,
        confirmDismiss: () async {
          // always returning false so it doesn't get dismissed
          return false;
        },
        onDismissed: (){
           // perform your action here 
        },
      ),
)

Currently (at the time of writing this v2.0.0), when false or null is returned from confirmDismiss the onDismissed never gets called back.

Here the docs:

  /// Gives the app an opportunity to confirm or veto a pending dismissal.
  ///
  /// If the returned Future<bool> completes true, then this widget will be
  /// dismissed, otherwise it will be moved back to its original location.
  ///
  /// If the returned Future<bool> completes to false or null the [onDismissed]
  /// callback will not run.
  final ConfirmDismissCallback? confirmDismiss;

So to get the desired behavior the action to be performed should be right before returning false in the confirmDismiss, like:

ActionPane(
      dragDismissible: true,
      dismissible: DismissiblePane(
        closeOnCancel: true,
        dismissThreshold: 0.9,
        confirmDismiss: () async {
          //TODO: perform your action here 
          // always returning false so it doesn't get dismissed
          return false;
        },
        onDismissed: (){
           // Never gets called back
        },
      ),
)

@YagneshVerve
Copy link

Any new update on this?

@YagneshVerve
Copy link

I didn't find any solution! how to archive this in the latest version of flutter_slidable(3.0.0)

@victor-kotov
Copy link

I didn't find any solution! how to archive this in the latest version of flutter_slidable(3.0.0)

Hi, It doesn't work for you even if you put the action before "return false"? If it works, you don't need onDismissed to be called.

confirmDismiss: () async { //TODO: perform your action here // always returning false so it doesn't get dismissed return false; },

@nicolasvahidzein
Copy link
Author

For some reason i got this working already, not sure when it happened lol. Here is my code: Thanks for your input @victor-kotov

Slidable(
	key: Key(_notification.hashCode.toString()),
	direction: Axis.horizontal,
	endActionPane: ActionPane(
		motion: DrawerMotion(),
		dragDismissible: true,
		dismissible: DismissiblePane(
			onDismissed: () {
				
				print('on dismissed callback');
				
			},
			closeOnCancel: true,
			confirmDismiss: () async {
				
				if (_notification!.read == true) {
					_swipedAction('unread');
				} else {
					_swipedAction('read');
				}
				
				return false;//to prevent actually dismissing the tile
				
			},
		),
		children: [
			
			SlidableAction(
				flex: 1,
				backgroundColor: Colors.blue,
				foregroundColor: Colors.white,
				onPressed: (contexto) {
					
					if (_notification!.read == true) {
						//it is INDEED read
						
						_swipedAction('unread');
						
					} else {
						//it is NOT yet read, it is UNREAD
						
						_swipedAction('read');
						
					}
					
					Slidable.of(contexto)?.close();
					
				},
				icon: _notification!.read == true ? FontAwesomeIcons.book : FontAwesomeIcons.readme,
				//label: 'label text goes here',//no label text for now
			),
			
		],
	),
	child: GestureDetector(
		behavior: HitTestBehavior.translucent, //this is to make sure it works on empty areas inside containers
		onTap: () {
			_showNotificationDialog();
		},
		child: Column(
			children:<Widget>[
				Container(
					color: Colors.transparent,
					height: 110,
					padding: EdgeInsets.fromLTRB(20, 0, 0, 0),
					child: Column(
						children: <Widget>[
							Row(
								mainAxisAlignment: MainAxisAlignment.start,
								children: <Widget>[
									
									Visibility(
										visible: _showImage(),
										child: Padding(
											padding: const EdgeInsets.fromLTRB(0, 8, 0, 8),
											child: Row(
												mainAxisAlignment: MainAxisAlignment.start,
													children: <Widget>[
														
														Container(
															height: 90,
															width: 90,
															child: CachedNetworkImage(
																key: ValueKey<String>(_imageUrl()),
																imageUrl: _parseMediaCdnUrl.parse(
																	relativeUrl: _imageUrl(), 
																	appStore: widget.appStore,
																),
																imageBuilder: (context, imageProvider) {
																	
																	return Container(
																		height: 90,
																		width: 90,
																		decoration: BoxDecoration(
																			borderRadius: BorderRadius.all(Radius.circular(500)),
																			border: Border.all(
																				color: Theme.of(context).primaryColor,
																				width: 2,
																			),
																			image: DecorationImage(
																				image: imageProvider,
																				fit: BoxFit.cover,
																			),
																		),
																	);
																	
																},
																progressIndicatorBuilder: (context, url, downloadProgress) {
																	return Container(
																		height: 75,
																		width: 75,
																		decoration: BoxDecoration(
																			borderRadius: BorderRadius.all(Radius.circular(500)),
																			color: Colors.white,
																		),
																		child: Center(
																			child:CircularProgressIndicator(
																				value: downloadProgress.progress,
																			),
																		),
																	);
																},
																errorWidget: (context, url, error) => Icon(Icons.error),
															),
														),
														
														SizedBox(width: 15),
														
													]
											),
										)
									),
									
									Expanded(
										child: Container(
											child: Column(
												crossAxisAlignment: CrossAxisAlignment.start,
												mainAxisAlignment: MainAxisAlignment.spaceAround,
												children: <Widget>[
													
													Text(
														_notification!.title,
														overflow: TextOverflow.ellipsis,
														maxLines: 2,
														style: Theme.of(context).textTheme.bodyMedium!.merge(
															TextStyle(
																fontWeight: _notification!.read
																? FontWeight.w500
																: FontWeight.w700,
															),
														),
													),
													
													Text(
														_notification!.time,
														style: Theme.of(context).textTheme.bodySmall!.merge(
															TextStyle(
																fontWeight: _notification!.read
																? FontWeight.w500
																: FontWeight.w700,
															),
														),
													)
													
												],
											),
										),
									),
									
									Container(
										height: 100,
										width: 40,
										child: Center(
											child: Container(
												height: 20,
												width: 20,
												decoration: BoxDecoration(
													borderRadius: BorderRadius.all(Radius.circular(500)),
													color: _notification!.read
													? Colors.transparent
													: Theme.of(context).primaryColor,
												),
											),
										),
										
									),
									
								],
							),
							
						],
					),
				),
				
				Container(
					padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
					child: Divider(
						height: 1,
					),
				),
				
			]
		),
	),
	
),

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

No branches or pull requests

5 participants