to achieve this
currently I use this code below
Slidable(
child: ProductListItem(product: product),
endActionPane: ActionPane(
motion: const StretchMotion(),
children: [
SlidableAction(
onPressed: (context) {
//
},
backgroundColor: Colors.orange,
foregroundColor: Colors.white,
icon: Icons.edit,
label: "edit".tr(),
),
SlidableAction(
onPressed: (context) {
//
},
backgroundColor: Colors.red,
foregroundColor: Colors.white,
icon: Icons.delete,
label: "delete".tr(),
),
],
),
),
I need to swipe in the right side to open that endPaneActions.
what I want is ....
if I tap that list item, then it will programmatically open that endPaneActions. how to do that?
from the tutorial on Youtube in here , it seems I can use the code below
final slidable = Slidable.of(context);
final isClosed = slidable.renderingMode == SlidableRenderingMode.none;
if (isClosed) {
slidable.open();
}
but it seems that code is obsolete, I can't find .renderingMode method on version 1.2.0
what is the latest version to programmatically open 'end actions pane' ?
finally I can make tap to open slidable programmatically on version 1.2.0. I got a clue from austin's answer on Github
Slidable(
child: LayoutBuilder( // <---- add LayoutBuilder
builder: (contextFromLayoutBuilder, constraints) {
return GestureDetector( // <--- add Gesture Detector
child: YourListItem(), // <--- your list item in here
onTap: () {
final slidable = Slidable.of(contextFromLayoutBuilder);
slidable?.openEndActionPane(
duration: const Duration(milliseconds: 500),
curve: Curves.decelerate,
);
},
);
},
),
endActionPane: ActionPane( // <--- I use endActionPane in here
motion: const StretchMotion(),
children: [],
),
)
as you can see, I add LayoutBuilder and GestureDetector inside the Slidable widget. LayoutBuilder is used to get the 'latest' context inside the Slidable widget, so the slidable value will not be null.
NOTE:
I use endActionPane here, so I use openEndActionPane method. if you use startActionPane, then you should use openStartActionPane method instead
Related
I have a SelectableText Widget with a string which is a phone number
Starts with +
Has 12 digits
When the text is selected, the option to call it doesn't appear.
If I open the same text for example in a google search as below, I can see the option to call it. How can I make that in Flutter?
You may use the contextMenuBuilder property for this.
It will help you creating a different context menu depending on the current state of the user's selection:
More info: see contextMenuBuilder property in SelectableText widget doc
SelectableText(
'data to show',
contextMenuBuilder: (_, textState) => Row(
children: [
if (isPhoneNumber(textState.textEditingValue.text))
Container(), //Widget to make the phone call here
],
),
),
bool isPhoneNumber(String selection) {
if (!selection.startsWith('+')) return false;
return RegExp(r'^[0-9]+$').hasMatch(selection.substring(1));
}
I solved it by looking at the example pointed out by #Luis Utrera
Solution:
contextMenuBuilder: (context, EditableTextState editableTextState) {
return AdaptiveTextSelectionToolbar(
anchors: editableTextState.contextMenuAnchors,
children: [
Padding(
padding: const EdgeInsets.all(10),
child: IconButton(
icon: Icon(Icons.call),
onPressed: () {
// TODO: launch call app
},
),
),
...editableTextState.contextMenuButtonItems
.map((ContextMenuButtonItem buttonItem) {
return CupertinoButton(
borderRadius: null,
onPressed: buttonItem.onPressed,
padding: const EdgeInsets.all(10.0),
pressedOpacity: 0.7,
child: Text(
CupertinoTextSelectionToolbarButton.getButtonLabel(
context,
buttonItem,
),
),
);
})
.toList()
.cast(),
],
);
},
I am pretty new to flutter/dart, so this might be a silly question...
I wanted to have a search bar, that when tapped the first time, displays a series of listview tiles (like pre-canned search terms). I wanted a subsequent tap to then open the soft keyboard for user input. As it stands now, a single tap opens the listview tiles, and also opens the soft keyboard.
After some looking around, I am thinking I would need to wrap the searchbar in a GestureDetector, and handle the tap / double-tap gestures through that. What I can't quite figure out, is how to tie the GestureDetector gestures, ontap and ondoubletap, to the child widget actions... I think when the searchbar gets focus (onTap), the soft keyboard opens, so not sure if that behavior can be (easily) uncoupled...
The flutter cookbook example uses this:
ScaffoldMessenger.of(context).showSnackBar(snackBar);
but the API docs say this only manages snackbars and MaterialBanners:
"Manages SnackBars and MaterialBanners for descendant Scaffolds."
Here is the framework I have so far:
Widget searchBar() {
//final FloatingSearchBarController searchBarController = FloatingSearchBarController();
return
GestureDetector(
onTap: () =>{},
onDoubleTap: () => {},
child: FloatingSearchBar(
controller: searchBarController,
hint: "search",
openAxisAlignment: 0.0,
width: 600,
axisAlignment: 0.0,
scrollPadding: const EdgeInsets.only(top: 16, bottom: 20),
elevation: 4.0,
onQueryChanged: (query) {
},
builder: (BuildContext context, Animation<double> transition) {
return ClipRRect(
child: Material(
color: Colors.white,
child: Container(
color: Colors.white,
child: Column(
children: [
ListTile(
title: const Text('Item 1'),
onTap: () {},
),
ListTile(
title: const Text('Item 2'),
onTap: () {},
),
ListTile(
title: const Text('Item 3'),
onTap: () {},
),
],
),
),
)
);
},
)
);
Any thoughts would be greatly appreciated!
I have a page containing many widgets which is opened in view only mode. i used AbsorbPointer for ignoring user inputs. but in some cases i have to get onTap event on one button which is inside AbsorbPointer. how can i achieve that ?
I tried using GestureDetector but its not giving onTap event.
any idea??
AbsorbPointer(
absorbing:true,
child: Column(children: [
Text("HELLO"),
Text("HELLO 2"),
GestureDetector(
onTap: () {
showToast("I tried this");
},
child: IconButton(
icon: Icon(
Icons.local_offer,
color: Colors.red,
),
onPressed: () {
print("I need this event");
},
),
)
]),
);
use absorbing: property for your cases... set it to false in the case you want to allow the GestureDetector inside
I'm using showMenu() to dispaly popup menu. Usually when you use PopupMenuButton it has the onSelected option, but you don't seem to have it with showMenu().
I tried wrapping the contents of PopupMenuItem inside GestureDetector, but that makes the clickable area just way too small. See picture below, the smaller rectangle is my GestureDetector (which works but is too small) and the bigger rectangle is the inkwell which comes with PopupMenuItem.
So my question is, how should I handle PopupMenuItem presses when I don't have the onSelected property?
EDIT:
Here is the code. I have ListTiles, which call this method on LongPress:
void _showOptionsMenu(int hiveIndex) {
final RenderBox overlay = Overlay.of(context).context.findRenderObject();
showMenu(
context: context,
position: RelativeRect.fromRect(
// magic code from stackoverflow, positions the PopupMenu on your tap location
_tapPosition & Size(40, 40),
Offset.zero & overlay.size,
),
items: [
PopupMenuItem(
value: 0,
child: Row(
children: [
Icon(Icons.edit),
Text("Edit"),
],
),
),
PopupMenuItem(
value: 1,
child: Row(
children: [
Icon(Icons.delete),
Text("Delete"),
],
),
),
],
);
You can't wrap the PopupMenuItems inside GestureDetector, since the items property only allows PopupMenuItems.
There is no need to wrap items into gesture detector.. show menu is an async method which returns value of the item menu. When you press any of the item you get back the value of that pressed item. With that value you can do whatever you want. Check this code
Future<void> _showOptionsMenu(int hiveIndex) async {
int selected = await showMenu(
position: RelativeRect.fromLTRB(60.0, 40.0, 100.0, 100.0),
context: context,
items: [
PopupMenuItem(
value: 0,
child: Row(
children: [
Icon(Icons.edit),
Text("Edit"),
],
),
),
PopupMenuItem(
value: 1,
child: Row(
children: [
Icon(Icons.delete),
Text("Delete"),
],
),
),
],
);
if (selected == 0) {
print('handle edit');
} else {
print('handle delete');
}
}
I am using the flutter Slidable widget inside a SliverList, where the list elements are pulled from an array. I use setState to update the list.
The problem I am having is that after the list update, I can see all new elements correctly, but the slidable functionality doesn't work. However, after entering a new page with push and leaving with pop, the slidable functionality starts working.
Why is this happening?
return SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => Card(
child: InkWell(
child: Slidable(
key: Key(_fileList[index].key),
actionPane: SlidableDrawerActionPane(),
child: Container(
child: ListTile(
onTap: () {
...
},
title: Text(_fileList[index].subtitle),
subtitle: Text(_fileList[index].subtitle),
),
),
secondaryActions: <Widget>[
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () {
...
}
),
],
),
),
),
childCount: _fileList.length,
),
);
Updating is done like this:
setState(() {
_fileList = newFileList;
});
i think you may try not to test on hot reload
just type in terminal : flutter run
Never mind, i accidentally disabled and then re-enabled the SlidableController.