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!
Related
Hi I managed to create a button that will show a tooltip and that tooltip will have a text content and a button, that button will redirect my app to my privacy policy page, the problem is when I redirect my app to that page using the button inside my tooltip.
All of my GestureDetector become disabled / not working even when I tried to do some simple task such as print().
Anyone know how to fix this ?
Here's my code:
ReusableTooltip(
tooltipHeader: '',
tooltipText: 'deviceContactClause',
tooltipDirection: AxisDirection.down,
tooltipChild: Container(
alignment: Alignment.center,
width: 45,
height: 40,
color: Colors.transparent,
child: SvgPicture.asset(
'assets/logo/Information.svg',
),
),
additionalWidget: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const PrivacyPolicyPage()
),
);
},
child: Container(
child: Text('seePrivacyPolicy',
),
),
),
Try this Gesture behavior
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
},
),
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
I have a TextField inside of an InkWell with an onLongPress() callback. The problem is, despite the fact that even when long pressing on the TextField, I see the ripple effect on InkWell, but the onLongPress() does not run after the long press time passes. It only gets me into editing Text. When pressing on the bottom side of the Card, everything runs fine.
In short: On tap I want to get into TextField editing. On long press I want to trigger the onLongPress(), not the TextField, even if I am pressing on it.
How do I do this? Thank you.
InkWell(
onLongPress: () {
// do stuff
}
child: ListTile(
title: TextField(),
),
),
You can use the AbsorbPointer widget to ignore the TextField gesture recognizer:
InkWell(
onLongPress: () {
print('onLongPress');
},
child: AbsorbPointer(
child: ListTile(
title: TextField(),
),
),
)
To still enabling the editing of TextField when single tapping on it, you can use FocusNode like this:
InkWell(
onLongPress: () {
print('onLongPress');
},
onTap: () => node.requestFocus(),
child: AbsorbPointer(
child: ListTile(
title: TextField(
focusNode: node,
controller: textController,
),
),
),
)
#Bach 's answer helped me to find a solution. Thank you!
InkWell(
onLongPress: () {
// do stuff
},
child: ListTile(
title: GestureDetector(
onTap: () => FocusScope.of(context).requestFocus(_focusNode),
child: AbsorbPointer(
child: TextField(
focusNode: _focusNode,
),
),
),
),
The only problem is now that I started messing with focusNode, multiple input fiels are focusing at the same time. But that is a whole other story ;)
UPD: Just realised, that I can't move text cursor this way. So not useful.
It seems that IntrinsicWidth widget can find the right balance between long press and text editing.
The rationale behind is that IntrinsicWidth will let the TextField shrink to its minimum width, therefore avoiding a gesture collision with the InkWell
So your solution can be like this:
InkWell(
onLongPress: () {
// do stuff
}
child: ListTile(
child: IntrinsicWidth(
title: TextField(
//remember to make some hints here
//because with intrinsicwidth if your textfield is empty it might disappear
),
),
),
),
So I'm searching for a Menu often found in a Settings Screen. It's used to select a Setting.
It opens when you press on a ListTile and then it fills the mayority of the Screen, while the borders are transparent. In the menu you have to select one of the options.
An example usecase of that would be to select a Language(onTap of the ListTile opens a Menu where you can select between all the avaliable languages)
It is similar to that of a PopupMenuButton, however as already mentioned it fills most of the screen, and the individual selectable items have a radiobutton in front of the text(probably RadioListTiles)
I hope someone gets what I'm talking about, because for the past 3 hours I'm searching for this widget but just find articles about the PopupMenuButton over and over.
Edit: I finally found an app that uses the feature I'm looking for
: https://imgur.com/a/A9k71io
By clicking on the first ListTile in the first Picture, the dialog in the second picture opens up.
Hopefully this custom widget is something roughly what you want, try to copy and paste it in your project and play with it.
this is made using the Dialog widget, to exit the Dialog you can tap out of it/ press the device back arrow and I added a small back icon on the top left corner.
tell me if it helped :)
class TestPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;// the device size
return Scaffold(
body: Center(
child: ListTile(
tileColor: Colors.grey[300],
title: Text(
'Language',
style: TextStyle(fontSize: 25),
),
onTap: () => showDialog(
context: context,
builder: (context) => Dialog(
insetPadding: EdgeInsets.all(20),
child: Container(
color: Colors.white,
height: deviceSize.height,
width: deviceSize.width,
child: Column(
children: [
Row(
children: [
IconButton(
color: Colors.red,
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
],
),
Spacer(),
Text('Pick A Language'),
Spacer(),
],
),
),
),
),
),
),
);
}
}
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.