How to add scroll indicator in ListView - flutter

Is there any way to show the scroll indicator on the ListView?
Here is my basic code:
ListView.builder(
itemCount: 50,
itemBuilder: (context, index) => ListTile(title: Text("Item= ${index + 1}"),),
)

Thanks to Günter Zöchbauer.
You can wrap your ListView in Scrollbar
Scrollbar(
child: ListView.builder(
itemCount: 50,
itemBuilder: (context, index) => ListTile(title: Text("Item= ${index + 1}"),),),
)

I think better to use CupertinoScrollbar instead of Scrollbar. CupertinoScrollbar is can touch and scroll to the bottom..
Ex:
CupertinoScrollbar(
child: ListView.builder(...),
Or
Scrollbar(
child: ListView.builder(...),

You can implement this designer scrollbar library :
draggable_scrollbar
alphabet scrolling
OR
You can wrap ListView in Scrollbar widget
Scrollbar(
child: ListView.builder(...),
)

Create a ScrollController variable (ScrollController _scrollController);
Instatiate _scrollController inside initState() or wherever you want, _scrollController = ScrollController();
Add _scrollController variable inside Scrollbar and ListView properties,
controller:_scrollController
Here's the code:
ScrollController _scrollController;
#override
void initState() {
super.initState();
_scrollController = ScrollController();
}
Scrollbar(
isAlwaysShown: true,
controller: _scrollController,
child: ListView(
controller: _scrollController,
)
if you don't want it always shown set to false
thumbVisibility: false,

Scrollbar(
thickness: 10,
isAlwaysShown: true,
child: ListView.builder(
itemCount: _controller().transactonsList.length,
itemBuilder: (context, index) {
return Card(
elevation: 5,
child: Container(
padding: const EdgeInsets.only(bottom: 16),
height: 80,
child: Row(
children: [
SizedBox(width: 10),
amountOfTransaction(index),
SizedBox(width: 16),
dateAndTitleOfTransaction(index),
],
),
),
);
},
),
)

final ScrollController _scroll = ScrollController();
#override
Widget build(BuildContext context) {
(...)
child: ListView.builder(
controller: _scroll,
)
}

If u need to style your scroll bar a bit wrap the ListView in RawScrollbar and use the same scroll controller instance for both widgets
final ScrollController _scrollController = ScrollController();
#override
Widget build(BuildContext context) {
(...)
child: RawScrollbar(
controller: _scrollController,
thumbColor: Colors.redAccent,
radius: const Radius.circular(8),
crossAxisMargin: 2,
child: ListView.builder(
controller: _scrollController,
itemCount: 50,
itemBuilder: (context, index) => ListTile(
title: Text("Item= ${index + 1}"),
),
),
),
}

Scrollbar(
child:ListView.builder(
itemCount:20,
itemBuilder:(c,i) => MyItem(i),
),
),
You have to give itemcount as how many list you have
-----Example: itemCount: items.length,-----

Related

Flutter Card Swipe Animation with forward and reverse methode without a loop

can i implement my own card swip animation ?
what i want is something similar to this package here. but the slides should shown from the top like so: (and without a loop)
my code:
final controller = SwiperController();
List<Widget> _pages = [
Container(color: Colors.blue),
Container(color: Colors.black),
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: new Swiper(
loop: false,
controller: SwiperController(),
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: _pages[index],
);
},
itemCount: _pages.length,
itemWidth: 400.0,
itemHeight: 700.0,
layout: SwiperLayout.TINDER,
),
);
}
}
can you suggest me a way to reach that and thanks.
My editor warns me about this:
The library 'package:flutter_swiper/flutter_swiper.dart' is legacy, and shouldn't be imported into a null safe library.
So I guess you should search for a up-to-date, null-safe package which does the same.
And for the vertical layout that you want to achieve... Can't you just rotate the whole swiper widget by 90 degrees?
Like so:
#override
Widget build(BuildContext context) {
return Scaffold(
body: RotatedBox(
quarterTurns: 1,
child: Swiper(
loop: false,
controller: SwiperController(),
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: _pages[index],
);
},
itemCount: _pages.length,
itemWidth: 400.0,
itemHeight: 700.0,
layout: SwiperLayout.TINDER,
),
),
);
}

Flutter The Scrollbar's ScrollController has no ScrollPosition attached

I get this error when using the AppBar:
The Scrollbar's ScrollController has no ScrollPosition attached.
This is my CustomScrollBar:
class CustomScrollBar extends StatelessWidget {
final Widget child;
final ScrollController scrollController;
const CustomScrollBar({
required this.scrollController,
required this.child,
});
#override
Widget build(BuildContext context) {
return RawScrollbar(
thumbColor: AppColors.gray,
radius: Radius.circular(8),
thickness: 4,
isAlwaysShown: true,
controller: scrollController,
child: child,
);
}
}
I should be always visible. And this is how I use it:
child: CustomScrollBar(
scrollController: _scrollControllerForScrollBar,
child: SingleChildScrollView(
controller: _scrollControllerForScrollBar,
child: Padding(
padding: EdgeInsets.all(7.0.scaled),
child: Container(
width: double.infinity,
child: Text(
'any text bla bla bla \n\n\n this is a lot of \n text \n .'
),
),
),
),
),
As you can see both the ScrollBar and the SingleChildScrollView use the same ScrollController. I have no idea why this error occurs. Any idea what I am missing here?
I was using a ScrollBar with a ListView widget and was getting this error in the debug console. To get rid of it, I had to set the ScrollController on both widgets.
final yourScrollController = ScrollController();
Scrollbar(
isAlwaysShown: true,
thickness: 10,
controller: yourScrollController, // Here
child: ListView.builder(
padding: EdgeInsets.zero,
scrollDirection: Axis.vertical,
controller: yourScrollController, // AND Here
itemCount: yourRecordList?.length
....
)
)
Let's assume you're using both Scrollbar widget and ListView widget as a child of the scrollbar - Both of them should have the same controller as :
ScrollController _controller = ScrollController();
Scrollbar(
controller: _controller,
child: ListView(
controller: _controller,
....), // ListView
) // Scrollbar
Remove the scrollController entirely and that should fix the problem. that is how I fixed my code so your code should look something like this
class CustomScrollBar extends StatelessWidget {
final Widget child;
const CustomScrollBar({
required this.child,
});
#override
Widget build(BuildContext context) {
return RawScrollbar(
thumbColor: AppColors.gray,
radius: Radius.circular(8),
thickness: 4,
isAlwaysShown: true,
child: child,
);
}
}
and the second part should be like this
child: CustomScrollBar(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(7.0.scaled),
child: Container(
width: double.infinity,
child: Text(
'any text bla bla bla \n\n\n this is a lot of \n text \n .'
),
),
),
),
),
The following assertion was thrown during a scheduler callback:
The Scrollbar's ScrollController has no ScrollPosition attached
A Scrollbar cannot be painted without a ScrollPosition.
The Scrollbar attempted to use the provided ScrollController. This
ScrollController should be associated with the ScrollView that the
Scrollbar is being applied to. When providing your own
ScrollController, ensure both the Scrollbar and the Scrollable widget
use the same one.
This is flutter's bug, https://github.com/flutter/flutter/issues/82573.
It is fixed on the flutter master branch:
flutter channel master
flutter upgrade
If you use nested scroller like this:
Expanded(
flex: 2,
child: Center(
child: Scrollbar(
child: SingleChildScrollView(
primary: true,
child: Scrollbar(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
.....)
You can fix the issue adding this line to first Scrollable view:
primary: true
The UI plotter wants know start position for the scroller both on mobile and low resolutions on desktop with size:
MediaQuery.of(context).size.shortestSide < 600
For this error, you have to define same 1 scrollController for both ScrollBar and SingleSchildScrollView/ListView:
For example from my prj:
final ScrollController _scrollController = ScrollController(); //define just 1 controller
final _currencyFormatter = NumberFormat('#,##0.00', 'vi_VN');
final double _safeSpaceToShowToolTip = 1.4;
final double _fixedChartHeight = 350.0;
int _touchedIndex = -1;
#override
Widget build(BuildContext context) {
return Scrollbar(
controller: _scrollController, // and use it both here
isAlwaysShown: true,
trackVisibility: true,
radius: Radius.circular(6.0),
child: SingleChildScrollView(
controller: _scrollController, // AND HERE
scrollDirection: Axis.horizontal,
physics: BouncingScrollPhysics(),
child: Container(
margin: EdgeInsets.only(bottom: R.dimens.mediumSpacing),
height:
R.dimens.getSpecificSize(_fixedChartHeight, isForHeight: true),
width: R.dimens
.getSpecificSize(_fixedChartHeight * 1.9, isForHeight: false),
child: BarChart(
_barChartData(),
),
),
),
);
}

Flutter listview builder Scroll controller listener not firing inside list view?

I have a listview builder widget inside another list view. Inner listview listener is not firing when scrolling position reaches to its end.
initState() {
super.initState();
_scrollController.addListener(() {
if (_scrollController.position.maxScrollExtent ==
_scrollController.position.pixels) {function();}
}
Container(
child: Listview(
children: <Widget>[
Container(),
ListView.builder(
controller: _scrollController,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return Container();
},
),
]
)
)
You might have SingleChildScrollView attached before any widget :
so attach _scrollController to singleChildScrollView not listview
body: SingleChildScrollView(
controller: _scrollController,
child: Column(
children: [
_chips(),
SizedBox(
height: 10,
),
_slider(),
_showGrid(),
],
),
),
the list view must scroll otherwise it won't work. Not only you have to remove the NeverScrollableScrollPhysics() but also add that list view into some container and set its height smaller then overall height of your ListView. Then the listView begin to scroll and the function will be triggered
ScrollController _scrollController = ScrollController();
List<int> list = [1, 2, 3, 4, 5];
initState() {
super.initState();
_scrollController.addListener(() {
if (_scrollController.position.maxScrollExtent ==
_scrollController.position.pixels) {
print('firing');
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: ControlBar(
title: Text('Home'),
),
),
body: ListView(
children: <Widget>[
Container(
height: 150,
child: ListView.builder(
controller: _scrollController,
shrinkWrap: true,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text(list[index].toString()));
},
),
),
],
),
);
}

Flutter: How can I use DraggableScrollableActuator.reset AND the ScrollController from DraggableScrollableSheet for a nested list?

I am getting this error.
The following assertion was thrown building _InheritedResetNotifier(dirty):
flutter: ScrollController attached to multiple scroll views.
flutter: 'package:flutter/src/widgets/scroll_controller.dart':
flutter: Failed assertion: line 111 pos 12: '_positions.length == 1'
It seems I can either attach DraggableScrollableSheet's ScrollController to the nested list OR use DraggableScrollableActuator.reset(context) to reset the extent. I don't see why I can't do both. Is this a bug? Is there a work around or another way?
Here is my code:
class InterfaceSelector extends StatefulWidget {
#override
InterfaceSelectorState createState() => InterfaceSelectorState();
}
class InterfaceSelectorState extends State<InterfaceSelector> {
double initialChildSize = 0.5;
double minChildSize = 0.5;
double maxChildSize = 0.7;
#override
Widget build(BuildContext context) {
return DraggableScrollableActuator(
child: DraggableScrollableSheet(
initialChildSize: initialChildSize,
minChildSize: minChildSize,
maxChildSize: maxChildSize,
builder: (BuildContext ctx, ScrollController scrollController) {
return SingleChildScrollView(
controller: scrollController,
child: Container(
height: MediaQuery.of(context).size.longestSide * .7,
color: Theme.of(ctx).primaryColor,
child: DefaultTabController(
length: 4,
child: Column(
children: <Widget>[
Material(
color: Theme.of(ctx).accentColor,
child: TabBar(
tabs: [
Tab(text: "One"),
Tab(text: "Two"),
Tab(text: "Three"),
Tab(text: "Four"),
],
),
),
Expanded(
child: TabBarView(
children: [
One(),
Two(),
Three(scrollController),
Four(),
],
),
),
],
),
),
),
);
},
),
);
}
}
class Three extends StatefulWidget {
ScrollController scrollController;
Three(this.scrollController);
#override
_ThreeState createState() => _ThreeState();
}
class _ThreeState extends State<Three> with AutomaticKeepAliveClientMixin {
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
Stuff stuff = Provider.of<Stuff>(context);
return Column(
children: <Widget>[
MaterialButton(onPressed: () {
DraggableScrollableActuator.reset(context);
}),
Expanded(
child: GridView.builder(
controller: widget.scrollController,
padding: const EdgeInsets.all(10),
itemCount: stuff.all.length,
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
value: stuff.all[i],
key: UniqueKey(),
child: StuffCard(i, stuff.all[i], stuff),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
),
),
],
);
}
}
Your GridView doesn't need scrolling - scrolling is provided by your SingleChildScrollView. Don't pass the scrollController to GridView, set physics: NeverScrollableScrollPhysics(), in your grid builder instead:
GridView.builder(
physics: NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(10),
itemCount: stuff.all.length,
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
value: stuff.all[i],
key: UniqueKey(),
child: StuffCard(i, stuff.all[i], stuff),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
),

Card not clickable in a Stack

I am following https://github.com/devefy/Flutter-Story-App-UI to build some UI components but I can't seem to make the cards clickable.
The PageView builder is supposed to manipulate the currentPage value to change the page, but the PageView builder is on top of the stack and blocks all GestureDetectors under it.
I can't think of any solutions atm, any help is appreciated.
PageController cardController =
PageController(initialPage: images.length - 1);
cardController.addListener(() {
setState(() {
currentPage = cardController.page;
});
});
Stack(
children: <Widget>[
StackedCards(currentPage,postList),
Positioned.fill(
child: PageView.builder(
itemCount: images.length,
controller: cardController,
reverse: true,
itemBuilder: (context, index) {
return Container();
},
),
)
],
)
Some clickable widgets : GestureDetector, InkWell, InkResponse
GestureDetector(
onTap: ...,
child: Stack(
children: <Widget>[
StackedCards(currentPage,postList),
Positioned.fill(
child: PageView.builder(
itemCount: images.length,
controller: cardController,
reverse: true,
itemBuilder: (context, index) {
return Container();
},
),
)
],
));