How to scroll to an index by its index number in flutter listview? - flutter

I have a listview . I want to go to a certain widget by it's corresponding index number.
I've tried with ScrollController, but it need offset value to jumpTo the index. But I want to jumpTo a widget by using its index number.
Please, help me to fix it
Thanks in advance.

Unfortunately, ListView has no built-in approach to a scrollToIndex() function. You’ll have to develop your own way to measure to that element’s offset for animateTo() or jumpTo(), or you can search through suggested solutions/plugins from other posts such as:
flutter ListView scroll to index not available
Flutter: Scrolling to a widget in ListView
(the general scrollToIndex issue is discussed at flutter/issues/12319 since 2017, but still with no current plans)
But there is a different kind of ListView that does support scrollToIndex:
ScrollablePositionedList
scrollable_positioned_list
dependency: flutter_widgets
You set it up exactly like ListView and works the same, except you now have access to a ItemScrollController that does:
jumpTo({index, alignment})
scrollTo({index, alignment, duration, curve})
Simplified example:
ItemScrollController _scrollController = ItemScrollController();
ScrollablePositionedList.builder(
itemScrollController: _scrollController,
itemCount: _myList.length,
itemBuilder: (context, index) {
return _myList[index];
},
)
_scrollController.scrollTo(index: 150, duration: Duration(seconds: 1));
(note that this library is developed by Google but not by the core Flutter team.)

Related

How can I add pages to a flutter listview builder?

Instead of infinite scrolling in a Listview.builder.
I want to be able to see x amount of items in my ListView and then going on to the next page should show the next x amount of items.
What I have so far is just a standard ListView.builder:
Listview.Builder(
itemCount: data.length
itemBuilder:(context, index){
return Card(
child: ListTile(
title: data[index]
)
);
}
)
You can use a PageController to control which page is visible in the view. In addition to being able to control the pixel offset of the content inside the PageView, a PageController also lets you control the offset in terms of pages, which are increments of the viewport size.
The PageController can also be used to control the PageController.initialPage, which determines which page is shown when the PageView is first constructed, and the PageController.viewportFraction, which determines the size of the pages as a fraction of the viewport size.
Refer to :
geeksforgeeks
Flutter Docs
Hope this helps. Happy Coding :)

ListView.builder's index doesn't reset when calling setState. Found a weird fix for it. Is there a better solution? Why is this happening?

I have this listview.builder which is supposed to show some orders from an array of Order objects based on their status.
It looks kinda like this:
The List works just fine until, for some reason, when I scroll down and the viewport can only display the order with index (the one in the listview builder function) 5 and then press another category like "New", setState() is called and the whole thing rebuilds, but the builder's index starts at 5 and the listview.builder doesn't build anything from 0 - 4. I've printed the index in the builder and caught this bug, but I still don't understand why this is happening.
This is what my listview.builder code looks like:
ListView.builder(
controller: _scrollController,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
print("INDEX: $index");
return _showOrder(index);
},
itemCount: orders.length,
),
This is the code for _showOrder():
Widget _showOrder(int i) {
String _currOrderStatus = orders[i].orderStatus;
/// _selectedOrderStatus is just a String which changes depending on the selected category of orders.
/// e.g. "New" or "Past"
return _currOrderStatus == _selectedOrderStatus
? ShowMyOrderWidget()
: SizedBox(
/// AND FOR SOME REALLY WEIRD REASON, THIS FIXES THE PROBLEM
/// It works with any height, as long as it's not 0, but if I have a lot of them, then the
/// layout gets spaced out and messy. With such a low number, this is highly unlikely, but
/// still seems like a stupid fix.
/// Why does this work? Why is this happening? Is there a better way to fix it?
height: 0.000000001,
);
}
And I just call setState() in the onPressed() function of those buttons on top of the screen.
Changing the items inside the ListView doesn't reset scroll position.
Since you're already assigning a ScrollController to your ListView, try calling "jumpTo(0.0)" to reset it's scroll position before calling setState().
_scrollController.jumpTo(0.0);

ReorderableListView inside SingleChildScrollView/Column

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.

How to use detect changes in elements of an array using provider?

I started developing my first app with flutter and I have some questions.
I have a screen that contains a Horizontal ListView where each item represents a month and occupy the entire screen. Each item is another list of itens. It's basically a list showing expenses for every month. I'm controlling state using Provider, and I'm having trouble to detect changes in a month. For example, I'm in january, but I added an expense in february, so the february item must detect the change and rewrite. I haven't been able to do it so far. Here is the screenshots of the app:
I have a provider that has an array of "Periods". And a "Period" is a class that represents a month, and contains an array of expenses.
I guess I'm not organising my data the right away, I'd appreciate if someone could point me in the right direction.
EDIT:
So, I watched this video here: https://www.youtube.com/watch?v=d_m5csmrf7I, and that helped me a little at least on how to detect changes in nested providers. I basically did this:
Widget build(BuildContext context) {
...
final size = MediaQuery.of(context).size;
final financeiro = Provider.of<Financeiro>(context);
return ImprovedListView.builder(
controller: _listController,
scrollDirection: Axis.horizontal,
itemCount: financeiro.periodos.length,
itemSize: size.width,
physics: const NeverScrollableScrollPhysics(),
initialScrollOffset: financeiro.indexMesAtual * size.width,
itemBuilder: (ctx, index) {
final periodo = financeiro.periodos[index]; //get a piece of the list and pass to another change notifier provider
return ChangeNotifierProvider<Periodo>.value(
value: periodo,
child: PeriodoFinanceiro(
key: ValueKey('${periodo.ano}${periodo.mes}'),
index: index,
scrollTo: scrollTo,
carregarDadosIniciais: carregarDadosIniciais,
excluirLancamento: excluirLancamento,
),
);
};
}
Now I just have to figure out how to better control the scrolloffset of the list when its re-rendered.
Thanks

The efficient way to implement a vertically translating widget on user drag

I want to translate a widget vertically as the user drags. I tried implementing it using two options:
AnimationController
Value notifier.
So when I use the animation controller the scroll is not very smooth and the widget is being scroll after a delay even when the duration of the animation is 1 milliseconds.
When I implement it using value notifier it is much better but still not as smooth as the ListView scroll. Is there a better way to scroll\translate a widget on user drag?
I found a better solution for this. Although it can be achieved using Gesture detector but that is not as smooth. Flutter has another wonderful widget for this and that is DraggableScrollableSheet.
If you want container for a Scrollable list that responds to drag gestures by resizing the scrollable until a limit is reached, and then scrolling this is the widget you should be using.
DraggableScrollableSheet(
initialChildSize: .70,
minChildSize: .70,
builder: (BuildContext context, ScrollController scrollcontroller){
scrollcontroller.addListener((){
});
return Container(
child: ListView.builder(
controller: scrollcontroller,
itemCount: widget.songs.length,
itemBuilder: (BuildContext context, int index) {
return buildSongRow(widget.songs[index]);
})
);
})
The above list will be place at the 70 percent of the height of the screen initially. When you scroll up it drags the list up to the top and then the list scrolls as a normal listview. When you reach the top while scrolling, the list drags down to the initial position(70 percent of height).