How to make a bottom navbar which the bottom navbar item get data from list?
bottom navbar example from flutter documentation
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
Create a custom class
class MyTabItem {
String title;
IconData icon;
MyTabItem(this.name, this.icon);
}
Create list of tabs:
List<MyTabItem> _items = [
MyTabItem('Home', Icons.home),
MyTabItem('Business', Icons.business),
MyTabItem('School', Icons.school),
];
Create a method to iterate through the _items collection and returns List<BottomNavigationBarItem>
List<BottomNavigationBarItem> getBottomTabs( List<MyTabItem> tabs) {
return tabs
.map(
(item) =>
BottomNavigationBarItem(
icon: Icon(item.icon),
label: item.title,
),
)
.toList();
}
Finally, call the method:
bottomNavigationBar: BottomNavigationBar(
items: getBottomTabs(items),
),
Answer was inspired by #Muldec response here: Flutter: Show different icons based on value
try this:
List<String> items = ['Home', 'Business', 'School'];
bottomNavigationBar: BottomNavigationBar(
items: items.map((item) {
Widget itemIcon = Icon(Icons.home);
if(item == 'Home')
{
itemIcon = Icon(Icons.home),
}else if(item == 'Business')
{
itemIcon = Icon(Icons.business),
}else if(item == 'School')
{
itemIcon = Icon(Icons.school),
}
BottomNavigationBarItem(
icon: itemIcon ,
label: item,
),
}).toList(),
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
Not allowed to comment Jim's message.
I used his code (works fine) but needs correction here I think:
List<String> items = ['Home', 'Business', 'School'];
bottomNavigationBar: BottomNavigationBar(
items: items.map((item) {
Widget itemIcon = Icon(Icons.home);
if(item == 'Home')
{
itemIcon = Icon(Icons.home),
}else if(item == 'Business')
{
itemIcon = Icon(Icons.business),
}else if(item == 'School')
{
itemIcon = Icon(Icons.school),
}
return BottomNavigationBarItem( // add return
icon: itemIcon ,
label: item,
); // replace , with ;
}).toList(),
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
Related
class _SimpleDialogState extends State<SimpleDialog> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _textEditingController = TextEditingController();
#override
void initState() {
super.initState();
baseurl = Prefs().geturlBase();
}
#override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('Base URL'),
content: Form(
key: _formKey,
child: TextFormField(
keyboardType: TextInputType.multiline,
maxLines: null,
//controller: _textEditingController,
initialValue: baseurl,
onChanged: (val) {
setState(() {
baseurl = val;
print(baseurl);
});
},
decoration: InputDecoration(
hintText: "Please Enter Base Url",
border:
OutlineInputBorder(borderRadius: BorderRadius.circular(15)),
),
validator: (value) {
// return value!.isNotEmpty ? null : "Enter Base Url";
return Uri.parse(value.toString()).host == ''
? "Enter Base Url"
: null;
},
)),
actions: <Widget>[
Center(
child: InkWell(
onTap: () {
buildShowDialog(context);
if (_formKey.currentState!.validate()) {
baseurl = baseurl.trim();
checkBaseUrl(baseurl, context);
// Navigator.of(context).pop();
print('baseurl=====base------$baseurl');
}
},
child: Container(
width: 100,
height: 40,
padding: EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(20.0),
),
child: Text(
"Connect",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
),
)
],
);
}
}
This is a dialog box where I can change my baseURL. Now, I need history when I touch textfield, history should appear and I can able to select the data from history to text field and also able to delete history, not all history particular data from that list. how can I able to achieve this kinda logic??.
An input_history_text_field widget is automatically saved and suggested as you type.
Whenever I add an item to my least it adds to the list at the current state but when I reopen after pop context the item is no more there
*How can I have the items in list permanently *enter image description hereenter image description hereenter image description hereenter image description hereenter image description here
class Prabesh extends StatefulWidget {
#override
_PrabeshState createState() => _PrabeshState();
}
class _PrabeshState extends State<Prabesh> {
final List users = [
'Ram',
'Shyam',
'Hari',
'Paudel',
'Pandey',
'Sashwat',
'Kismat',
];
// ondlt(Key key) {
// for (int i = 0; i <= users.length; i++) {
// var a = users.elementAt(i);
// if (key == a.key) {
// users.removeAt(i);
// }
// }
// }
void onClk() {
myDialog(BuildContext, context);
}
final myUser = TextEditingController();
myDialog(BuildContext, context) {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return AlertDialog(
title: Text('Add a user'),
content: TextFormField(
controller: myUser,
maxLength: 20,
decoration: InputDecoration(
hintText: 'Enter Username',
),
),
actions: [
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: Text('Cancel')),
ElevatedButton(
onPressed: () {
setState(() {
if (myUser.text.isEmpty) {
return Navigator.pop(context);
} else {
users.add(myUser.text);
return Navigator.pop(context);
}
});
},
child: Text('Add'),
),
],
);
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Prabesh'),
leading: BackButton(
onPressed: () => Navigator.pop(context),
),
),
body: ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return Card(
elevation: 10,
child: ListTile(
// key: Key(users[index]),
//onLongPress: () => ondlt(key),
onTap: () {},
title: Text(users[index]),
trailing: Icon(Icons.menu),
leading: CircleAvatar(
child: Text(users[index].substring(0, 1)),
),
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => onClk(),
child: Icon(Icons.add),
),
),
);
}
}
You must save your data locally or on an online database.
For saving data on mobile storage you can use this package.
But for saving data on an online database you can use Firebase or you must develop a web server.
Instead of making isSelected bool variable, i'll like to make it as index of selected. then check for the index of selected in reportReasons list.
This is to know which reason is being selected. Also, how do I then make the selected container change color if isSelected is not a bool?
Thank you.
final List<String> reportReasons = [
'blah',
'blah blah',
'blah blah blah'
];
List<String> chosenReasonsToReport = [];
bool isSelected = false;
Container(
child: Wrap(
children: reportReasons
.map((reportReason) => GestureDetector(
onTap: () {
setState(() { if (isSelected = false) {
isSelected = true;
} else {
isSelected = false;
}});
if (reportReason.isSelected && chosenReasonsToReport.length < 3) {
chosenReasonsToReport.add('${reportReason}');
print(chosenReasonsToReport);
} else {
chosenReasonsToReport.remove('${reportReason}');
print(chosenReasonsToReport);
}
},
child: Container(
margin: EdgeInsets.only(
right:
MediaQuery.of(context).size.width * 0.021,
bottom: MediaQuery.of(context).size.height *
0.009,
),
decoration: BoxDecoration(
color: isSelected
? Color(0xff4aa3f8)
: Color(0xff3a327f),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color:
Colors.grey[50].withOpacity(0.60))),
padding: EdgeInsets.symmetric(
horizontal:
MediaQuery.of(context).size.width *
0.027,
vertical:
MediaQuery.of(context).size.height *
0.0045),
child: Text(
reportReason,
style: TextStyle(
fontSize: 13.5,
color: isSelected
? Color(0xff231b6a)
: null),
),
),
))
.toList()),
You can use a couple of approaches:
A set of indexes:
class _MyScreenState extends State<MyScreen> {
static const List<String> _reportReasons = [
'blah',
'blah blah',
'blah blah blah'
];
Set<int> _chosenIndexes = {};
#override
Widget build(BuildContext context) {
return ListView(
children: List.generate(_reportReasons.length, (i) {
return Container(
// Change property based on report selection
color: _chosenIndexes.contains(i)
? Colors.green
: Colors.red,
child: CheckboxListTile(
// Accessing report name
title: Text(_reportReasons[i]),
// Accessing if report is selected
value: _chosenIndexes.contains(i),
// Selecting and unselecting report
onChanged: (v) {
setState(() {
if (v) {
_chosenIndexes.add(i);
} else {
_chosenIndexes.remove(i);
}
});
}
),
);
}),
);
}
}
A map of String and booleans:
class _MyScreenState extends State<MyScreen> {
final Map<String, bool> _reports = {
'blah': false,
'blah blah': false,
'blah blah blah': false,
};
#override
Widget build(BuildContext context) {
return ListView(
children: _reports.keys.map((report) {
return Container(
// Change property based on report selection
color: _reports[report]
? Colors.green
: Colors.red,
child: CheckboxListTile(
// Accessing report name
title: Text(report),
// Accessing if report is selected
value: _reports[report],
// Selecting and unselecting report
onChanged: (v) {
setState(() => _reports[report] = v);
}
),
);
}).toList(),
);
}
}
I have a list of users which show in a dropdown in a form which is then submitted, the list is empty, I have made a function which allows users to type a "name" into a TextFormField and it then adds that name to the list, it then appears on the dropdown, but when the page is reloaded the list item has gone.
example:
void savePerson() {
String newperson = _newPersonController.text;
_persons.add(newperson);
}
The function to save string to list
List<String> _persons = [
];
The List
TextFormField(
controller: _newPersonController,
decoration: InputDecoration(
hintText: 'Add New Person',
prefixIcon: Icon(
Icons.local_hospital,
size: 30,
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
)),
The TextFormField where the user inserts the name to be added
FlatButton(
onPressed: () {
savePerson();
setState(() {
_newPersonController.clear();
});
},
child: Text('Add Person'))
Button code
Just to be clear, it ADDS it to the list/dropdown - that works, but my list doesn't seem to be able to save info to it.
I'm fairly new to flutter - sorry for anything obvious.
The problem maybe the logic of the dropdown, and add the setState() when you add the item to the people list
I use this code:
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final TextEditingController _newPersonController =
new TextEditingController();
List<String> _persons = [];
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: Text('Material App Bar'),
),
body: Center(
child: Column(
children: <Widget>[
DropdownButton(
items: List.generate(
_persons.length,
(i) => DropdownMenuItem(
child: Text(_persons[i]),
)),
onChanged: (_) {}),
TextFormField(
controller: _newPersonController,
decoration: InputDecoration(
hintText: 'Add New Person',
prefixIcon: Icon(
Icons.local_hospital,
size: 30,
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
)),
FlatButton(
onPressed: () {
savePerson();
setState(() {
_newPersonController.clear();
});
},
child: Text('Add Person'))
],
),
),
),
);
}
void savePerson() {
String newperson = _newPersonController.text;
setState(() {
_persons.add(newperson);
});
}
}
Probably can help you
i created a search delegate class and what i want sounds logically simple but i cant wrap my head around it as i am new programming
i want to get the text or maybe i should say string of the text in the listTile i tap on ,
then pass that text to the showResult of search delegate and view it in a text widget
... here is my code
import 'package:flutter/material.dart';
import 'package:schooler/style/const.dart';
//follow steps 1 - 3
class DataSearch extends SearchDelegate<String> {
final List<String> languages = [//3.here is my list
'dart',
'Csharp',
'Java',
'JavaScript',
'C++',
'go ',
'python',
'php'
];
final List<String> recentSearch = [
'go ',
'python',
'php',
];
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = '';
},
)
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, null);
},
);
}
#override
Widget buildResults(BuildContext context) {
return Scaffold(
body: ListView(
physics: BouncingScrollPhysics(),
children: <Widget>[
Row(
children: <Widget>[
CircleAvatar(),
Text(languages[0].substring(query.length)),//2.i want to return the gotten index here
],
),
],
),
);
}
#override
Widget buildSuggestions(BuildContext context) {
final suggestionList = query.isEmpty
? recentSearch
: languages.where((element) => element.startsWith(query)).toList();
return ListView.builder(
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) => ListTile(
onTap: () {
showResults(context); //1.when i tap the item on the listTile i want it to get the index of the taped item
},
leading: query.isEmpty
? Icon(
Icons.history,
)
: Icon(Icons.search),
title: RichText(
text: TextSpan(
text: suggestionList[index].substring(
0,
query.length,
),
style: TextStyle(
color: kBlackColor,
fontWeight: kBold,
),
children: [
TextSpan(
text: suggestionList[index].substring(query.length),
style: TextStyle(color: kGreyColor),
),
],
),
),
),
itemCount: suggestionList.length,
);
}
}
here if i tap on 'go' it should get get the text and pass it to the showResult
here is my show result ..but i just hard coded my 'list[0]index in there' i guess what i am trying to say is get the text from the item i taped and show it here
First lets fix your itemBuilder in your ListView so it indexes each element and then add that index into your showResults() function call so you have access to it:
ListView.builder(
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) => ListTile( // Add index here to pass the index to the builder.
onTap: () {
showResults(context, index); // Add the index to function call
},
Just be sure your showResults() function is modified to accept an int index parameter, and while I dont see that function, I am assuming it calls buildResults() at some point which needs to be modified to accept an index:
#override
Widget buildResults(BuildContext context, int index) {
return Scaffold(
body: ListView(
physics: BouncingScrollPhysics(),
children: <Widget>[
Row(
children: <Widget>[
CircleAvatar(),
Text(languages[index].substring(query.length)),// Use the index here to return the desired text
],
),
],
),
);
}