Flutter how to get a popup menu on a ListTile? - flutter

I'm trying to get a popupmenu under a ListTile. The title displays a description, the subtitle displays the selected value with some message and the onTap opens the popupmenu in which a user can select a value.
I tried putting a DropdownButtonHideUnderline in the subtitle, but this displays an arrow and does not respond to the ListTile onTab obviously.
How can I get a popupmenu on a ListTile?

Maybe you can try PopuMenuButton,
PopupMenuButton<String>(
onSelected: (String value) {
setState(() {
_selection = value;
});
},
child: ListTile(
leading: IconButton(
icon: Icon(Icons.add_alarm),
onPressed: () {
print('Hello world');
},
),
title: Text('Title'),
subtitle: Column(
children: <Widget>[
Text('Sub title'),
Text(_selection == null ? 'Nothing selected yet' : _selection.toString()),
],
),
trailing: Icon(Icons.account_circle),
),
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
const PopupMenuItem<String>(
value: 'Value1',
child: Text('Choose value 1'),
),
const PopupMenuItem<String>(
value: 'Value2',
child: Text('Choose value 2'),
),
const PopupMenuItem<String>(
value: 'Value3',
child: Text('Choose value 3'),
),
],
)
Take a look at How to open a PopupMenuButton?

Related

Flutter UI Create menu with function after click icon more

Halo,
First, I wanna show you my current UI :
And here's the code for red circle function :
InkWell(
onTap: null,
child: Icon(Icons.more_horiz,
size: 18,
color: Color.fromRGBO(0, 0, 0, 0.25),
),
),
What action I needed is to show pop-up menu like this after click the icon, for example :
I need that to create edit and delete with function to navigate to another page, and need to know how to control menu position.
I already check on pub.dev, but it didn't resolve my problem.
Can anyone give me an advice?
Try this code :
the package is here : https://pub.dev/packages/pull_down_button
PullDownButton(
itemBuilder: (context) => [
PullDownMenuItem(
title: 'Menu item',
onTap: () => action(),
),
const PullDownMenuDivider(),
PullDownMenuItem(
title: 'Menu item 2',
onTap: () => action2(),
),
],
position: PullDownMenuPosition.under,
buttonBuilder: (context, showMenu) => CupertinoButton(
onPressed: showMenu,
padding: EdgeInsets.zero,
child: const Icon(CupertinoIcons.ellipsis_circle),
),
);
result :
You can try using PopupMenuButton you can find here an example
Try below code hope its help to you. and used PopupMenuButton
Declare Key Variable:
final GlobalKey menuKey = GlobalKey();
Widget:
InkWell(
onTap: () {
dynamic state = menuKey.currentState;
state.showButtonMenu();
},
child: PopupMenuButton(
key: menuKey,
itemBuilder: (_) => const <PopupMenuItem<String>>[
PopupMenuItem<String>(
child: Text('Show Test'),
value: 'Test',
),
PopupMenuItem<String>(
child: Text('Edit Test Solution'),
value: 'Edit',
),
],
onSelected: (_) {},
),
),
Result->

How to set the value of DropdownButton inside showDialog() method in Flutter?

I am trying to set the value of the drop down menu inside showDialog() method, but since it's not in in build method I can't set the state of the current value. So is there a solution for this?
Here's my code
showDialog(
barrierDismissible: false,
context: context,
builder: (context) => AlertDialog(
actions: [
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
'Cancel'
)),
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
'Submit',
style: FONT_BODY_TEXT.copyWith(fontSize: 18.0),
)),
],
content: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Select your new item',
),
DropdownButton<String>(
isExpanded: true,
value: _item,
hint: Text(
'Select an item',
),
onChanged: (newValue) {
setState(() {
_item = newValue;
});
},
items: MYLIST.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: FONT_BODY_TEXT,
),
);
}).toList(),
),
],
),
),
));
I need to get the new item from this method so I can submit the changes, that's why I am using showDialog() method so whenever I click on submit, the item is returned, and whenver I click on cancel it will not return an item. This is just for confirmation of the order.
Use StatefulBuilder to use setState inside Dialog and update Widgets only inside of it.
StatefulBuilder(builder: (context, setState) {
return DropdownButton<String>(
isExpanded: true,
value: item,
hint: Text(
'Select an item',
),
onChanged: (newValue) => {
setState(() {
item = newValue;
})
},
items: ['A', 'B', 'c'].map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}),

Understanding ListView.builder

Okay, so I think I am stuck with flutter builder a little bit.
I've created simple app, just to make my question easier:
I have a data class:
class DataLists {
List<ListTile> lists = [
ListTile(
leading: Text('Tile Leading 1'),
title: Text('Tile Title 1'),
subtitle: Text('Tile Subtitle 1'),
trailing: Text('Tile Trailing 1'),
),
ListTile(
leading: Text('Tile Leading 2'),
title: Text('Tile Title 2'),
subtitle: Text('Tile Subtitle 2'),
trailing: Text('Tile Trailing 2'),
),
ListTile(
leading: Text('Tile Leading 3'),
title: Text('Tile Title 3'),
subtitle: Text('Tile Subtitle 3'),
trailing: Text('Tile Trailing 3'),
),
ListTile(
leading: Text('Tile Leading 4'),
title: Text('Tile Title 4'),
subtitle: Text('Tile Subtitle 4'),
trailing: Text('Tile Trailing 4'),
),
ListTile(
leading: Text('Tile Leading 5'),
title: Text('Tile Title 5'),
subtitle: Text('Tile Subtitle 5'),
trailing: Text('Tile Trailing 5'),
),
];
}
And main dart file:
import 'package:flutter/material.dart';
import 'package:learning/data.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: TestTile(),
);
}
}
class TestTile extends StatefulWidget {
#override
_TestTileState createState() => _TestTileState();
}
class _TestTileState extends State<TestTile> {
DataLists dataLists = DataLists();
TextEditingController leadingController = TextEditingController();
TextEditingController titleController = TextEditingController();
TextEditingController subtitleController = TextEditingController();
TextEditingController trailingController = TextEditingController();
Future<String> createDialog(BuildContext context) {
return showDialog(context: context, builder: (context) {
return SimpleDialog(
title: Text('Input data: '),
children: [
TextField(
controller: leadingController,
),
TextField(
controller: titleController,
),
TextField(
controller: subtitleController,
),
TextField(
controller: trailingController,
),
MaterialButton(
child: Text('Submit'),
onPressed: () {
Navigator.of(context).pop(leadingController.text);
setState(() {
List<ListTile> tempList = dataLists.lists;
if (titleController.text.isNotEmpty && leadingController.text.isNotEmpty && subtitleController.text.isNotEmpty && trailingController.text.isNotEmpty) {
tempList.add(
ListTile(
leading: Text(leadingController.text),
title: Text(titleController.text),
subtitle: Text(subtitleController.text),
trailing: Text(trailingController.text),
),
);
dataLists.lists = tempList;
} else {
print('Null values');
}
leadingController.clear();
titleController.clear();
subtitleController.clear();
trailingController.clear();
});
},
),
],
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test Tile'),
),
body: Container(
child: SafeArea(
child: ListView(
children: <ListTile>[
for (ListTile e in dataLists.lists)
e
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
createDialog(context);
setState(() {
});
},
child: Icon(Icons.add),
backgroundColor: Colors.blue,
),
);
}
}
The problem is: I cannot make it work in other way. Can someone change my implementation to a ListView.builder? I am stuck a little bit :(
Key goal:
Idea:
Click on a button -> form appear -> after you press a submit button list is updated instantly
I'll add a delete function later, just learning docs, nothing more.
Can someone review my code and, if no one mind, try to rewrite the same idea, but using ListView.builder?
I've tried several times, but cannot get properties correctly from the form, and update listtile using builder, need help
Cheers!
ListView.builder requires a static height, so keep a track on that one. Now, coming to the question, that you want to use ListView.builder. You can do via this
Container(
height: give_your_height,
child: ListView.builder(
shrinkWrap: true,
itemCount: dataLists.lists.length,
itemBuilder: (context, index) {
return dataLists.lists[index];
}
)
)
Try this, it may solve your issue.
ListView(
children: [
for (ListTile e in dataLists.lists)
Card(child: e)
],
),
or with ListView.builder()
ListView.builder(
itemCount: dataLists.lists.length,
itemBuilder: (context, index) {
return dataLists.lists[index];
},
);
Further Reference: https://api.flutter.dev/flutter/material/ListTile-class.html

Problem with a widget not showing when using IconButton

I am facing a problem that my PopupMenuButton not showing when I click on, I tried many solutions but without success.
I am also searched in google but with not results.
I am afraid I am facing a bug.
Here is my code
enum MyMenuEntries { edit, delete }
IconButton(
icon: Icon(Icons.more_vert),
onPressed: () =>
PopupMenuButton<MyMenuEntries>(
onSelected:
(MyMenuEntries entry) {},
itemBuilder:
(BuildContext context) => [
PopupMenuItem<MyMenuEntries>(
value: MyMenuEntries.edit,
child: ListTile(
leading: Icon(Icons.edit),
title: Text("Edit")),
),
PopupMenuItem<MyMenuEntries>(
value: MyMenuEntries.delete,
child: ListTile(
leading: Icon(Icons.delete),
title: Text("Delete")),
),
],
))
Please any answer could help me.
Thanks!
Instead of using an IconButton, you can use the PopUpMenuButton as is and supply the icon to its icon property. It will automatically show the PopUpMenuButton items.
So you should remove the IconButton and your code will be:
PopupMenuButton<MyMenuEntries>(
onSelected:
(MyMenuEntries entry) {},
itemBuilder:
(BuildContext context) => [
PopupMenuItem<MyMenuEntries>(
value: MyMenuEntries.edit,
child: ListTile(
leading: Icon(Icons.edit),
title: Text("Edit")),
),
PopupMenuItem<MyMenuEntries>(
value: MyMenuEntries.delete,
child: ListTile(
leading: Icon(Icons.delete),
title: Text("Delete")),
),
],
icon: Icon(Icons.more_vert),
)

Customize Stepper in Flutter

I want to customize the Steppers in flutter.
How can I place the Step title to the left of each step bar?
How can I change the line bar to the dotted bar of the stepper?
And how can I customize the state of the step other than the 5 StepState provided like a round bubble?
Here is my code.
Container(
child: Stepper(
currentStep: 0,
controlsBuilder: (BuildContext context, {
VoidCallback onStepContinue,
VoidCallback onStepCancel
}) => Container(),
steps: [
Step(
content: Container(
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text('9:00Am - 10:00AM'),
Text(
'Everest Tour',
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
),
),
title: Text('9:00 AM'),
),
Step(
content: Text('2nd Data'),
title: Text('10:00 AM'),
state: StepState.editing,
isActive: true,
subtitle: Text('subtitle')
)
],
),
)
You can customize the Stepper widget by modifying the original Stepper widget class. Here's a customized Stepper widget I've created that can be configured with optional stepIndicatorAlignment and dottedLine arguments. The text on 'Continue' and 'Cancel' buttons can also be modified.
Here's a sample on how it can be implemented.
CustomStepper(
// stepIndicatorAlignment is set to StepIndicatorAlignment.left by default if not configured
stepIndicatorAlignment: StepIndicatorAlignment.right,
// dottedLine is set to false by default if not configured
dottedLine: true,
currentStep: _index,
onStepCancel: () {
if (_index > 0) {
setState(() {
_index -= 1;
});
}
},
onStepContinue: () {
if (_index <= 0) {
setState(() {
_index += 1;
});
}
},
onStepTapped: (int index) {
setState(() {
_index = index;
});
},
steps: <CustomStep>[
CustomStep(
title: const Text('Step 1 title'),
content: Container(
alignment: Alignment.centerLeft,
child: const Text('Content for Step 1'),
),
continueButtonLabel: 'YES',
cancelButtonLabel: 'NO',
),
CustomStep(
title: Text('Step 2 title'),
content: Container(
alignment: Alignment.centerLeft,
child: Text('Content for Step 2'),
),
),
],
),
In this similar Stack Overflow post, I've explained how I'm able to modify the stock Flutter Stepper widget.