Flutter list view navigation to categories - list

I'm learning Flutter. I have a ListView and I would like to make the list items clickable. My idea is that when the user clicks on an item, it will be directed to another screen. Each buttom should leads to different screen. I'm having trouble implementing it, I don't know what to use: gesture detector or ontap. What should I do? Should I use ListTile instead of ListView?list viewdata

If you're using a ListView.builder, you can use a ListTile to add an onTap.
ListView.builder(
itemBuilder: (_, i) {
return ListTile(
title: Text('$i'),
onTap: () {}, // Handle your onTap here.
);
},
)

well, you can use Inkwell. ListView.builder( itemBuilder: (_, i) { return InkWell( onTap: (){}, child: ///widget, ); }, ) link enter link description here

Related

How to add items to a list? Flutter

Here is what I'm trying to do.
Here is my ListItems class:
class ListItems {
String? title;
String? text;
DateTime? selectedDayTime;
ListItems(
{required this.title, required this.text, required this.selectedDayTime});
}
In my AddTask class, I'm trying to add some items to my list. Here is my code:
ElevatedButton(
onPressed: () {
setState(() {
itemList.add(
ListItems(
title: _titleController.text,
text: _textController.text,
selectedDayTime: _selectedDay,
),
);
Navigator.pop(context);
});
print(itemList.length);
},
child: Text("Add Task"),
),
itemList is a List list. However, everytime I try to add new item to my itemList, itemList.length never changes. I dont know why this happening so I need help.
Swap Navigator with print line.
ElevatedButton(
onPressed: () {
setState(() {
itemList.add(
ListItems(
title: _titleController.text,
text: _textController.text,
selectedDayTime: _selectedDay,
),
);
print(itemList.length);
//Navigator.pop(context); keep it here also
});
Navigator.pop(context);
},
child: Text("Add Task"),
),
Does it make any difference if you include your print statement inside the setState? I don't see any reason for your code not to work.
You could also try to type your itemList to be of type List<ListItems>, if you haven't already. I don't think it's causing any issues, but it can't hurt to be thorough.

Flutter list displaying erratically

I am having a problem with my lists in flutter not consistently keeping the order that I give them. I have a list: List alphabet = ['a', 'b', 'c', 'd'];, and am trying to display it with ListView.builder like this:
ListView.builder(
shrinkWrap: true,
itemCount: alphabet.length,
itemBuilder: (BuildContext ctxt, int index) {
return Center(
child: Text(alphabet[index]));
})
Usually this displays as "a b c d", but not always, sometimes it loads as "d, a, b, c" which is not acceptable. Once, it even came out as "d, a, c, b". How can I make it load the first way consistently?
I also have this line of code: var letterA = (alphabet).first;. Likewise it usually displays "a" but sometimes will display "d".
I couldn't find anything online about this problem, so I guess it is a silly mistake somewhere. I changed the page that includes the ListView from Stateful to Stateless hoping it would help but it didn't at all. And now I don't know what to do?
I could break up all my lists and write them letter by letter each time but I feel that is not the correct solution to my problem.
Edit:
Both alphabet and letterA are in a dart file together "mylists.dart" that just have that data, and then I imported it into this file:
import 'package:flutter/material.dart';
import 'package:flutterproject/mylists.dart';
import 'package:flutterproject/nextpage.dart';
class AlphabetPage2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: GestureDetector(
onTap: () => Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => NextPage(),
),
),
child: ListView.builder(
shrinkWrap: true,
itemCount: alphabet.length,
itemBuilder: (BuildContext ctxt, int index) {
return Center(
child: Text(alphabet[index]));
})),
),
));
}
}
mylists.dart looks like this:
List alphabet = ['a', 'b', 'c', 'd'];
var letterA = (alphabet).first;
List soups = ['tomato', 'chicken noodle', 'lentil'];
var soupA = (soups).first;
The order, though usually correct is not always correct. And in other pages when I call soupA I mostly get tomato, but sometimes get another one.

Manage items in a List with their ids

Let me explain, I have two List Views with Items. At the moment I don’t give an id to these items but I have a problem. In fact, when I remove an item from my favorites list, it doesn’t change the icon (favorite or not favorite) for the right item on the home_screen.
I want to get the place of the item in the menu screen so I can change the icon from the favorites list. I’m using the provider package.
And so I wonder if it wouldn’t be better to create an id for each item and store a List<int> and then create a List<Item> in my favorites list. Also, I can use this id to change the right icon.
But I don’t know how to use these ids to create a List and then change the right icon.
Illustrations of what I said :
Black heart = in favorite and White heart = not in favorite.
It is the wrong item which is deleting.
My code on Github ans some relevant parts of my code :
favModel.dart
class FavModel extends ChangeNotifier {
List<Item> favList = [];
List<bool> isInFav = [];
addInFavorite(title, description, index){
Item item = Item(title: title, description: description, );
favList.add(item);
isInFav[index] = true;
notifyListeners();
}
removeOfFavorite(int index, int index2){
favList.removeAt(index);
isInFav[index2] = false;
notifyListeners();
}
implement(){
isInFav.add(false);
}
}
favorite_screen.dart
class Favorite extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Favorite'),
),
body: Consumer<FavModel>(
builder: (context, favModel, child) {
return ListView.builder(
itemCount: favModel.favList.length,
itemBuilder: (context, index) {
return TextObject(favModel.favList[index].title,
favModel.favList[index].description),
Padding(
padding: const EdgeInsets.all(7.0),
child: GestureDetector(
child: Icon(
Icons.favorite,
color: Colors.red,
size: 32,
),
onTap: () {
favModel.removeOfFavorite(index, index);
}),
),
});
},
),
);
}
}
home_screen.dart
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
actions: [
IconButton(
icon: Icon(Icons.favorite_border),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
fullscreenDialog: true,
builder: (context) {
return Favorite();
},
),
),
),
],
),
body: Consumer<FavModel>(builder: (context, favModel, child) {
return ListView.builder(
shrinkWrap: false,
itemCount: itemData.length,
itemBuilder: (context, index) {
favModel.implement();
return TextObject(
itemData[index].title, itemData[index].description),
Padding(
padding: const EdgeInsets.all(7.0),
child: GestureDetector(
child: Icon(
favModel.isInFav.elementAt(index)
? Icons.favorite
: Icons.favorite_border,
color:
favModel.isInFav[index] ? Colors.red : null,
size: 32,
),
onTap: () {
favModel.isInFav[index]
? null
: Provider.of<FavModel>(context,
listen: false)
.addInFavorite(
itemData[index].title,
itemData[index].description,
index,
);
}),
);
});
}),
);
}
}
Where I want to get the index is in the favorite_screen.dart at this line favModel.removeOfFavorite(index, index);
I would suggest you to add bool isFavorite to your class Item and add an id for the class also. So you can avoid having two arrays.
And using the id will help you using some awesome methods like findWhere and removeWhere
EDIT
You can iterate the List using for
for(int i = 0;i<favList.length;i++){
if(favList[i].id == selectedItem.id){
favList[i].isSelected = true;
break;// break the loop no need to continue
}
}
notifyListeners()
Notice that now you have to pass Item instead of index

removing item from ListView.builder Flutter

hi may i ask how to remove an item from the ListViewBuilder,
normally it must be enough if i have an array let's call it x;
then i can remove any item that i want by using remoteAt
x.removeAt(index);
but in this case i couldn't know exactly how can i do that.
so i don't have an x array or list in this case , see please the code below.
i just declared how can i do that if i have a list and including it inside a list builder , then i can remove any widget on the screen by calling removeAt property
thanks in advance
child: Column(
children: <Widget>[BlocBuilder(
cubit: BlocProvider.of<AppBloc>(context),
builder: (BuildContext context, AppState state) {
if (state is AppUpdated && state.services.count > 0) {
return Expanded(
child: ListView.builder(
itemCount: state.services.count,
itemBuilder: (BuildContext context, int index) =>
Dismissible(
key: Key(state.service.toString()),
ListView.builder(
itemCount: state.services.count,
itemBuilder: (BuildContext context, int index) =>
Dismissible(
key: Key(state.service.toString()),
onDismissed: (direction) {
// Remove the item from the data source.
setState(() {
x.removeAt(index);
});
},
child: //your child here (maybe listivew)
),
),

Flutter: getting switch toggle values from dynamic form or why does state change rebuild differs

I have kind of a form where I can add cards, each having 5 textfields and 2 switches. I would like to use a method to build the switch code (and the textfield code, but that is working). However, the switches refuse to show their intended state. I saw couple of similar questions. However, most were solved with a list view listing all switched/checkboxes next to one another (I have multiple cards with multiple textfields and multiple switches, each). This was close, but I don't really understand the answer (within the comments)
Actually some answers come up with the same (I guess more or less same because mine isn't working) code storing the switch state in a bool list. When debugging I can see that the values are correctly stored in the list. However, the changed value is not rendered upon state change.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
var descrTECs = <TextEditingController>[];
var fixedSCs = [true]; //storing the switch values
var cards = <Card>[]; // storing the list of cards with forms
SizedBox createTextField(String placeholderStr, double fieldWidth) {
var tFieldController = TextEditingController();
switch (placeholderStr) { //switching placeholder to assign text controller to correct controller list
case "Description":
descrTECs.add(tFieldController);
break;
}
return SizedBox(width: fieldWidth, height: 25,
child: CupertinoTextField(
placeholder: placeholderStr,
controller: tFieldController,
),
);
}
SizedBox createSwitch(int pos) {
return SizedBox(width: 50, height: 25,
child: CupertinoSwitch(
value: fixedSCs[pos],
onChanged: (value) {
setState(() => fixedSCs[pos] = value); // value is stored in fixedSCs but not rendered upon rebuild
},
)
);
}
Card createCard() {
return Card(
child: Row(children: <Widget>[
Text('#p${cards.length + 1}:'),
Column(
children: <Widget>[
createSwitch(cards.length),
createTextField("Description", 70.0),
],),
],),
);
}
#override
void initState() {
super.initState();
cards.add(createCard()); // first card created upon start
}
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: SafeArea(
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder( // List Builder to show all cards
itemCount: cards.length,
itemBuilder: (BuildContext context, int index) {
return cards[index];
},
),
),
RaisedButton(
child: Text('add new'),
onPressed: () => setState(() {
fixedSCs.add(true); // bool element created to create next card
cards.add(createCard());} // create next card
),
),
],
),
),);
}
}
One thing I do not understand in general: Upon rebuild after a state change cards.length} should be my number of cards, let's say 3. And when it renders the 1st card, it passes the line Text("#p${cards.length + 1}"), so it should show #p3 and not #p1. What do I get wrong here?
I meanwhile got this working with quite some logic changes.
I put the switch builder into a stateless widget
class createSwitch extends StatelessWidget {
const createSwitch({
this.label, this.margin=const EdgeInsets.all(0.0), this.width, this.height, this.value, this.onChanged});
final String label; final EdgeInsets margin; final double width; final double height; final bool value;
final Function onChanged;
#override
Widget build(BuildContext context) {
return Container(
child: Row(
children: <Widget>[
Expanded(child: Text(label)),
CupertinoSwitch(
value: value,
onChanged: (bool newValue) {onChanged(newValue);},
),
],
),
),
} }
In the parent stateful controller I created a list to store the switches' state var parameterSCs = [true]; and each time I add a card I add a value whith clicking the button onPressed: () => setState(() {parameterSCs.add(true);}
I no longer store the cards widgets as a list. Instead, I build them directly in the code within a ListView.builder
ListView.builder(
itemCount: parameterSCs.length,
itemBuilder: (BuildContext context, int index) {
return Card( ...
In my real code I have 2 switches per card, so I always add 2 elements and the ListView count is then half of the parameterSCs' length.
I tried loads of approaches, this was the only one working