ReorderableListView inside SingleChildScrollView/Column - flutter

I need to put my reorderable list inside SingleChildScrollView, but the ReorderableListView() doesn't have shrink wrap like ListView(). Is there a work around to accomplish this layout without using an outdated unmaintained package? Although, I haven't tested those available outdated packages yet I don't know if they're built using different widgets or they're just building upon ReorderableListView() if so the error will persist.

you can wrap your ReorderableListView with Expanded Widget in Column.

The flutter team has released 2.0.1 stable recently, which shipped with a new designed ReorderableList class. As I tested, the ReorderableList class can work with Column and SingleChildScrollView smoothly.
code snippet like:
SingleChildScrollView(
child: Column(
children: [
ReorderableList(
controller: ScrollController(),
shrinkWrap: true,
itemCount: itemList.length,
itemBuilder: (BuildContext context, int index) {
final item = itemList[index];
return ReorderableDelayedDragStartListener(
index: index,
key: UniqueKey(),
ListTile(...),
);
},
onReorder: (int oldIndex, int newIndex) {...},
),
],
),
);

For me, I was using a Reorderable Listview inside a Column which was inside an ScrollView.
Tried multiple combinations but was getting the error, so I just wrapped each ListTile of the ListView in a container, and it worked for me. If that doesnt work then try limiting the height of each container.

Related

Flutter GridView: how to don't generate items when GridView is not primary

I try to make an apps using long GridView with complexe item. I use GridView.builder which is optimize and it creates visible items (and it do the job !).
But in my case, I need some widget before and I must add Column() and SingleChildScrollView.
When I do that I need to change GridView.builder with primary=false and shrinkWrap: true.
But now, all GridView items are generated.
EDIT: New demo
My wanted behavior is the mode "ColumnWithGrid".
Check this demo to understand issue.
Press top buttons to switch modes: open Console and check log
https://dartpad.dev/?id=4f60ffbf656767a6e5c5bccc280acd3a
I think "shrinkWrap" property must stay to false but I never success to keep it in this case.
My question:
How to use GridView.builder properly when I need to include it inside Column() or whatever ?
How to make the mode "ColumnWithGrid" without generate full list (using dev.pub, ...) ?
Thanks
After some search and experiment, I found some posts about this topic (which is true for GridView or ListView widget) and my conclusion is :
GridView doesn't work like I expect !
When I create just a single GridView, it's like I create a container of my full device area and I put GridView inside.
This "hidden container" just keep info visible inside this container area.
So if I include my GridView inside Column without any container, it doesn't create it for me and unroll all my data to compute properly size.
The feature that expected is : GridView computes only items at screen and unroll virtually data (so manage local/global slider position to create only item inside visible area).
I update my demo to show the effect about all cases.
Sources:
https://docs.flutter.dev/cookbook/lists/long-lists
https://medium.com/saugo360/flutter-creating-a-listview-that-loads-one-page-at-a-time-c5c91b6fabd3
A CustomScrollView in combination with SliverList and SliverGrid can be used to achieve lazy loading.
CustomScrollView(slivers: [
SliverList(
delegate: SliverChildListDelegate([
const Center(
child: Text(
"Header",
style: TextStyle(fontSize: 40),
),
),
]),
),
SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
delegate: SliverChildBuilderDelegate(
(context, index) {
print("generate the item $index");
return Container(color: Colors.blue);
},
childCount: 100,
),
),
]),
https://dartpad.dev/?id=9633305d9a2daa0905de852fa003aba1

Dynamic ListView of stateful widgets not working

Dears,
it could be just a mistake of mine but ...it's driving me crazy ;)
I have a ListView inside my statefulwidget:
Expanded(
child: ListView.builder(
padding: EdgeInsets.all(10.0),
itemCount: searchableFoodList.length,
itemBuilder: (BuildContext context, int index) {
print('4 - SFL - ${searchableFoodList[index].id} - ${searchableFoodList[index].name}');
return
FoodItem(
id: searchableFoodList[index].id,
baseUnit: searchableFoodList[index].baseUnit,
baseUnitS: searchableFoodList[index].baseUnitS,
baseVal: searchableFoodList[index].baseVal,
baseValCal: searchableFoodList[index].baseValCal,
mediumVal: searchableFoodList[index].mediumVal,
mediumValCal: searchableFoodList[index].mediumValCal,
name: searchableFoodList[index].name,
note: searchableFoodList[index].note
);
},
),
searchableFoodList is modified (according user selection) inside a setState().
Let say that we have a 3 FoodItem(s), so my searchableFoodList is [FoodItem-1, FoodItem-2, FoodItem-3] and everything is working fine.
If I select a single item in my list, let say "FoodItem-2", the searchableFoodList becomes [FoodItem-2] and the list displayed contains (correctly) just one item but it is FoodItem-1.
Note that I inserted a print ...and it prints "FoodItem-2"
I guess that the problem is that it is considered the "original list" and it is changed only the length of the list but the list itself is not re-generated.
I have no more ideas ...any suggestions to solve this problem?
P.S.
FoodItem is stateful widget as well (an animated one). I did something similar with using stateless widget and I didn't have any problem

Idea in order to address lack of scrollbar in Flutter web

I am new to flutter and using it for web. I see that there is no built in scrollbar when the page overflows the viewport
Would it be possible to somehow have a javascript script in the html that would check the height of the content periodically and add/remove scroll bar as necessary?
Does this make any sense?
Thank you
I'm not sure if its what you want but if you wrap your Listview with Scrollbar then you get the result you want:
Scrollbar(
child: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) => ListTile(title: Text("Item= ${index + 1}"),),),
)
You can find more here

Height of listview.builder depend on items count/context

Height of listview.builder depend on items count.I have different count of items and in all case i have different height of my listvuew.builder.Is it posible in flutter?
If you mean that you want to have different listview with different size, Yeah! it is possible. ListView automatically create the size for you. But you shared very little information and no code, so i persume you want to have a listView on different cases, then you can do it like this:
return Scaffold(
appBar: AppBar(
title:Text("ListView.builder")
),
body: ListView.builder(
itemCount: count, //the variable which holds the count.
itemBuilder: (BuildContext context,int index){
return ListTile(
//Your code
);
}
),
);
I hope it answers your question, if not try expanding your question or letting me know it in the comment. Happy coding:)

How to add items to a Row object at runtime in Flutter?

The most amazing part of Flutter is that every widget is an object. But, when I try to make an object from a Row and add a List of widgets to its children, I get this error on runtime:
Cannot add to an unmodifiable list
I'm currently creating my Row like this:
Row rowStar = Row();
rowStar.children.addAll(rowChildren);
Is this wrong? If so, what's the correct way?
1. Why it won't work
If all you want to do is add a list to a Row, you should create the list and then initialize the Row with it. You cannot add the list afterwards because Flutter's widgets typically have final fields/properties, which are not modifiable at runtime.
2. The Flutter Way
However, what you could do to dynamically modify the list is pass a function that builds your list internally at runtime. And that's exactly what the ListView.builder() constructor of ListView does.
For example, this the docs example for dynamically creating a List of Containers based on the the Lists entries and colorCodes.
final List<String> entries = <String>['A', 'B', 'C'];
final List<int> colorCodes = <int>[600, 500, 100];
ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: entries.length,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 50,
color: Colors.amber[colorCodes[index]],
child: Center(child: Text('Entry ${entries[index]}')),
);
}
);
You could add a button to .add, say, the letter D and the colorCode 400, to the respective Lists, and Flutter would render the respective Containers dynamically on the screen.
I'm not sure if I get it right, but what you're trying to do doesn't make sense. If you want to reuse a Row with widgets and information you can just build it once and save the whole thing as widget.
Try it like this:
Build a Row.
Create widgets for your children.
Display them as widgets of the row.
Row(
children: <Widget>[
customWidget1(),
customWidget2(),
customWidget3(),
],
)
Your custom widgets are the content of the Row then.
Hope it helps.
In my case, I can make a Row from a previously created List<Widget>:
Row calculateListOfStars(ranking) {
final List<Widget> rowList = [];
rowList.addAll([
// make my custom widget
]);
final Row rowStars = Row(
children: rowList,
);
return rowStars;
}
Use Listview:
ListView(
children: rowStar((data) {
return ListTile();
}).toList();