Unable to create dynamic list view with text and radio button in flutter
when i am creating dynamically(Fetching the data from service and binding the data with text ) list view with text and radio button when i am selecting radio button it is not showing selected (indicator );
import 'package:flutter/material.dart';
class DemoTest extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new DemoTestStatesFull(),
);}}
class DemoTestStatesFull extends StatefulWidget {
DemoTestState createState() => DemoTestState();
}
class DemoTestState extends State {
final List<String> floor_list = [
"floor1",
"floor2",
"floor3",
"floor4",
"floor5",
"floor6",
];
int _selectedIndex =0;
int _value2=0;
Container datacontainer=new Container();
_onSelected(int index) {
setState(() => _selectedIndex = index);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Dynamic View Example'),
),
body: Stack(
children: <Widget>[
new RaisedButton(
child: Text("Fetch Data"),
onPressed:() {setState(() {
datacontainer= DisplayData(floor_list);// Let Suppose Here getting data from web service after json parsing string list is
print("Button is clicked");
});}),
datacontainer,
],));}
Widget DisplayData(List<String>floorlist)
{
datacontainer =new Container(
height: 300.00,
width: 400.00,
child: ListView.builder(
itemCount: (floorlist.length),
itemBuilder: (context, i) {
return new InkResponse(
enableFeedback: true,
onTap: ()
{
print(" Card index is $i");
},
child:new Card(
color: _selectedIndex != null && _selectedIndex == i ? Colors.greenAccent : Colors.white,
elevation: 3.0,
margin: EdgeInsets.fromLTRB(5.00, 0.00, 5.00,5.00),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(padding: const EdgeInsets.fromLTRB(20.00,0.0, 0.0,0.0)),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(floorlist[i], style: new
TextStyle(fontSize: 20.0,
fontWeight: FontWeight.bold)),
),
Padding(padding: const EdgeInsets.fromLTRB(70.00,
0.0, 0.0,0.0)),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(floorlist[i], style: new
TextStyle(fontSize: 20.0,
fontWeight: FontWeight.bold)),
),
new Radio(
value: i,
groupValue: _value2,
onChanged:(int value)
{
setState(() {
_value2=value;
print("Radio index is $value");
});}),])));}
),);return datacontainer;}}
just i want to create dynamic list view with text and select able radio button
first you can easily use gestureDetector for the row without the radio button and
put radio button at trailing , listTile is like a row for the list and have title and trailing under it as a relative position inside the tile (listTile is the list row you want that contains text and a radio button) .
ps : GestureDetector is a widget so you can return it instead of the left side of the row.
return ListTile(
leading:GestureDetector(
child: //add the text here,
onTap: () {
//here handle the onclick for text
} ,
) ,
trailing://here add the radio button with onchanged normally,
);
hope that answers your question.
Related
This is a single page application.
I have created a drawer inside the Scaffold of HomePage. There are three list tile items in the list view below the title.
When I click the list tile I was able to change the title of the drawer through the onTap method.
But how can I replace the present list tile items with new list tile items after clicking any of the present list tile items.
In general how can I update the list tile items after pressing on any of the items in drawer
Before clicking an item
After clicking change font, the list is unchanged
What I want after clicking change font
I tried making a new function that returns a list view and called it in the setState inside onTap and also calling outside setState but inside the onTap
I did a simple sample here, you can check it out if it satisfies your need.Simple Drawer
you can run it on dart pad as well
Dart pad
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(),
drawer: const Drawer(child: MyDrawer()),
body: Center(
child: MyWidget(),
),
),
);
}
}
enum MenuItem {
font("Change Font",
['Commic Sans', 'Product Sans', 'Monserrat', 'ubuntu', 'unbounded']),
theme("Change Theme", ['dark', 'light']),
metrics("Change Metrics", ['small', 'medium', 'large']);
final String label;
final List<String> items;
const MenuItem(this.label, this.items);
}
class MyDrawer extends StatefulWidget {
const MyDrawer({super.key});
#override
State<MyDrawer> createState() => _MyDrawerState();
}
class _MyDrawerState extends State<MyDrawer> {
MenuItem? selectedMenu;
#override
Widget build(BuildContext context) {
return SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child:
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
const SizedBox(height: 20),
Text(
'Settings',
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 60),
Container(height: 1.0, color: Colors.grey),
const SizedBox(height: 60),
// if a menu item is selected, display its sub items
if (selectedMenu != null)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
BackButton(onPressed: (){
setState(() {
selectedMenu = null;
});
},),
for (var item in selectedMenu!.items)
InkWell(
onTap: () {
print(item);
},
child: Padding(
padding: const EdgeInsets.all(10),
child: Text(
item,
style: Theme.of(context).textTheme.bodySmall,
)))
])
else
for (var item in MenuItem.values)
InkWell(
onTap: () {
setState(() {
selectedMenu = item;
});
},
child: Padding(
padding: const EdgeInsets.all(10),
child: Text(
item.label,
style: Theme.of(context).textTheme.bodySmall,
)))
])));
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text(
'Hello, World!',
style: Theme.of(context).textTheme.headlineSmall,
);
}
}
I am a beginner in Flutter. I am trying to add a new list item widget to screen when floating action button is pressed. How do I achieve this?
I am trying to create a list of items. When the floating action button is clicked, a dialog box is prompted and user is asked to enter details. I want to add a new list item with these user input details.
This is my input_page.dart file which I am calling in main.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class MedPage extends StatefulWidget {
#override
_MedPageState createState()=> _MedPageState();
}
class _MedPageState extends State<MedPage> {
Future<String>createAlertDialog(BuildContext context) async{
TextEditingController customController= new TextEditingController();
return await showDialog(context: context,builder: (context) {
return AlertDialog(
title: Text("Name of the Pill"),
content: TextField(
controller: customController,
),
actions: <Widget>[
MaterialButton(
elevation: 5.0,
child: Text("OK"),
onPressed: (){
Navigator.of(context).pop(customController.text.toString()); // to go back to screen after submitting
}
)
],
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My med app'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget> [
Expanded(
child: ListView(
padding: const EdgeInsets.all(8),
children: <Widget>[
ReusableListItem(Color(0xFFd2fddf),"Name 1"),
ReusableListItem(Colors.orange,"Name 2"),
ReusableListItem(Color(0xFF57a1ab), "Name 3"),
],
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
print("Clicked");
createAlertDialog(context).then((onValue){
print(onValue);
setState(() {
});
});
},
child: Icon(Icons.add),
),
);
}
}
class ReusableListItem extends StatelessWidget {
ReusableListItem(this.colour,this.pill);
Color colour;
String pill;
#override
Widget build(BuildContext context) {
return Container(
height: 50,
margin: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: colour,
borderRadius: BorderRadius.circular(15.0)
),
child: Center(
child: Text(pill)
),
);
}
}
You don't need to change much in your code, maintain a variable that stores the values entered to be able to show them in the list. You should use Listview.builder() in order to dynamically render the items.
Here's your code:
class MedPage extends StatefulWidget {
#override
_MedPageState createState() => _MedPageState();
}
class _MedPageState extends State<MedPage> {
List<String> items = [];
Future<String> createAlertDialog(BuildContext context) async {
TextEditingController customController = new TextEditingController();
return await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Name of the Pill"),
content: TextField(
controller: customController,
),
actions: <Widget>[
MaterialButton(
elevation: 5.0,
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop(customController.text
.toString()); // to go back to screen after submitting
})
],
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My med app'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
return ReusableListItem(Color(0xFFd2fddf), items[index]);
},
itemCount: items.length,
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
print("Clicked");
createAlertDialog(context).then((onValue) {
// print(onValue);
setState(() {
items.add(onValue);
});
});
},
child: Icon(Icons.add),
),
);
}
}
class ReusableListItem extends StatelessWidget {
ReusableListItem(this.colour, this.pill);
final Color colour;
final String pill;
#override
Widget build(BuildContext context) {
return Container(
height: 50,
margin: const EdgeInsets.all(8),
decoration:
BoxDecoration(color: colour, borderRadius: BorderRadius.circular(15.0)),
child: Center(child: Text(pill)),
);
}
}
Firstly you need to use ListView.builder() rather than ListView because you have dynamic content. Also you need to hold your items in a list.
// create a list before
ListView.builder(
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return Text(list[index]);
}
)
When you click on FloatingActionButton() you will call AlertDialog() method.
FloatingActionButton(
onPressed: (){
AlertDialog(
content: Form(), // create your form here
actions: [
// add a button here
]
)
})
This method will show a dialog(you will add a form inside of the dialog). When the user completes the form(after clicking the button) you will add a new object to the list and update the state with setState({})
onPressed: (){
setState({
// add new object to the list here
});
Navigator.pop(context); // this will close the dialog
}
I've tried to populate the dropdown menu button with the data from the SQLite database.
Then on the onTap Function I wanted to navigate to the selected category.
When I tap on the category it does not navigate.
I have saved each category with an id in the database which is used the identify the selected item.
Here is the code:
'''
class _HomeState extends State<Home> {
TodoService _todoService;
var _selectedValue;
var _categories = List<DropdownMenuItem>();
List<Todo>_todoList=List<Todo>();
#override
initState(){
super.initState();
_loadCategories();
}
_loadCategories() async {
var _categoryService = CategoryService();
var categories = await _categoryService.readCategory();
categories.forEach((category) {
setState(() {
_categories.add(DropdownMenuItem(
child: Text(category['name']),
value: category['name'],
onTap: ()=>Navigator.of(context).push(MaterialPageRoute(builder:(context)=>TodosByCategory(category: category['name'],))),
));
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _globalKey,
appBar: AppBar(
actions: <Widget>[
DropdownButtonHideUnderline(
child: DropdownButton(
value: _selectedValue,
items: _categories,
dropdownColor: Colors.blue,
style: TextStyle(color: Colors.white,fontSize: 16.0),
iconDisabledColor: Colors.white,
iconEnabledColor: Colors.white,
onChanged: (value) {
setState(() {
_selectedValue = value;
});
},
),
),
'''
Here is the todosByCategory():
'''
class _TodosByCategoryState extends State<TodosByCategory> {
List<Todo>_todoList=List<Todo>();
TodoService _todoService=TodoService();
#override
initState(){
super.initState();
getTodosByCategories();
}
getTodosByCategories()async{
var todos=await _todoService.readTodoByCategory(this.widget.category);
todos.forEach((todo){
setState(() {
var model= Todo();
model.title=todo['title'];
model.dueDate=todo['dueDate'];
_todoList.add(model);
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Todos By Category'),
),
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: _todoList.length,
itemBuilder: (context, index){
return Padding(
padding: EdgeInsets.only(top:8.0, left: 8.0, right: 8.0),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
elevation: 8.0,
child: ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(_todoList[index].title)
],
),
subtitle: Text(_todoList[index].dueDate),
// trailing: Text(_todoList[index].dueDate),
),
),
);
},),
)
],
),
);
}
}
'''
Please help me out.
Instead of writing the navigation code inside onTap of DropdownMenuItem, you can write it inside onChanged of DropdownButton where you are also getting the category name string as the value. It should work then.
I am a newbie in a flutter. I have a simple app I need to show the JSON value in my container and on tap, the second value will show.
class _MyHomePageState extends State<MyHomePage> {
final List _questions = [
{'would': 'Coffe', 'rather': 'Tea'},
{'would': 'Coffe', 'rather': 'Tea'},
{'would': 'Coffe', 'rather': 'Tea'},
];
#override
Widget build(BuildContext context) {
final PrimaryColor = const Color(0xff404040);
final PreferredSizeWidget appBar = AppBar(
centerTitle: true,
title: Text(
'Would you Rather',
style: TextStyle(fontFamily: 'FredokaOne'),
),
backgroundColor: PrimaryColor,
);
return Scaffold(
backgroundColor: Color(0xff404040),
appBar: appBar,
body: Column(
children: <Widget>[
InkWell(
onTap: () => print("And after click here it will change both question"),
child: Container(
child: Text(_questions[0].would,),
),
),
InkWell(
onTap: () => print("And after click here it will change both question"),
child: Container(
child: Text(_questions[0].rather,),
),
),
],
));
}
}
Here I have a list of questions. In 1 array there are 2 values. I need to show these 2 values in each container and when I tap on the container the next array will appear.
Create a variable index that will increment in nextQuestion function is triggered when one of the containers is tapped. The increment will stop once it reaches the last element of _questions List. Finally, use the index when assigning the values of the Text inside the Containers to change when changing the index.
class _MyHomePageState extends State<MyHomePage> {
final List _questions = [
{'would': 'Coffe', 'rather': 'Tea'},
{'would': 'Blue', 'rather': 'Red'},
{'would': 'Green', 'rather': 'Yellow'},
];
int index = 0;
#override
Widget build(BuildContext context) {
final PrimaryColor = const Color(0xff404040);
int size = _questions.length;
void nextQuestion(){
if(index < size - 1)
setState(() {
index++;
});
print(index);
}
final PreferredSizeWidget appBar = AppBar(
centerTitle: true,
title: Text(
'Would you Rather',
style: TextStyle(fontFamily: 'FredokaOne'),
),
backgroundColor: PrimaryColor,
);
return Scaffold(
backgroundColor: Color(0xff404040),
appBar: appBar,
body: Column(
children: <Widget>[
InkWell(
onTap: nextQuestion,
child: Container(
height: 100,
child: Text(_questions[index]['would']),
),
),
InkWell(
onTap: nextQuestion,
child: Container(
height: 100,
child: Text(_questions[index]['rather']),
),
),
],
));
}
}
I want to show entered text in scrambled form. ie, each letter of the word need to display in individual Container in a row. For this, I am taking text input, storing it in List<String> and then scrambling it using shuffle() and then using List.generate to return Container with Text, as below:
List<Widget> _generateJumble(String input) {
inputList = input.split('');
var shuffleList = inputList.toList()..shuffle();
print(shuffleList);
return List<Widget>.generate(shuffleList.length, (int index) {
return Container(
width: 50,
color: Colors.blue,
child: Text(shuffleList[index].toString(),
style: TextStyle(color: Colors.white),
)
);
});
}
I am calling above method onTap of a button upon which the scrambled form of the input should be displayed. But I am not sure how to display the result of above method in UI. How should I use this method so that the returning Container based on shuffleList.length will be displayed in UI as below ?
RaisedButton(
onPressed: () {},
child: Text('Clear'),
)
],
),
),
Row(
children: <Widget>[
// ? _displayJumble()
]
)
This is my solution:
1) Press a button, scrable the string and set it to the a list
2) setState and show the list to the user
This is the widget code:
class _MyHomePageState extends State<MyHomePage> {
List<String> inputList = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Wrap(
children: inputList.map((s) {
return Container(
width: 50,
color: Colors.blue,
child: Text(
s,
style: TextStyle(color: Colors.white),
),
);
}).toList(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_generateJumble('Random string');
});
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
List<Widget> _generateJumble(String input) {
inputList = input.split('');
inputList = inputList.toList()..shuffle();
print(inputList);
}
}
I used the widget Wrap because automatically wrap the widget when there is no space available for it. You can use whatever you like to use.
This is the screen result:
Before press the button:
After press the button:
Please check the below solution of it, I have used the Wrap widget for it
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutterlearningapp/colors.dart';
class HomeScreen extends StatefulWidget {
var inputVales;
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _HomeScreen();
}
}
class _HomeScreen extends State<HomeScreen> {
List<String> charcaterArray = new List<String>();
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Home"),
),
body: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: TextField(
decoration: InputDecoration(labelText: 'Enter Words'),
onChanged: (text) {
setState(() {
widget.inputVales = text;
charcaterArray.clear();
for (var i = 0; i < widget.inputVales.length; i++) {
var character = widget.inputVales[i];
if (character != " ") {
charcaterArray.add(character);
}
}
});
},
),
),
Wrap(
spacing: 6.0,
runSpacing: 6.0,
children:
List<Widget>.generate(charcaterArray.length, (int index) {
return Container(
height: MediaQuery.of(context).size.height * 0.1,
width: MediaQuery.of(context).size.width * 0.1,
decoration: BoxDecoration(
color: Colors.lightGreen,
borderRadius: BorderRadius.all(Radius.elliptical(4.0, 4.0)),
),
child: Center(
child: Text(
charcaterArray[index],
style:
TextStyle(color: Colors.deepOrange, fontSize: 20.0),
),
),
);
/*Chip(
label: Text(charcaterArray[index]),
onDeleted: () {
setState(() {
charcaterArray.removeAt(index);
});
},
);*/
}),
)
],
));
}
}
And here is the output of it