Unable to scroll on widget even after wrapping column() with SingleChildScrollView() - flutter

Here is the root widget . The widget has a child BuyerPostList() which is a ListView type of widget. I removing the SingleChildScrollView() gives a render exception .After adding it the error no longer appears but the page is still not scrollable.
class PostsPage extends StatelessWidget {
final AuthService _auth = AuthService();
#override
Widget build(BuildContext context) {
return StreamProvider<List<BuyerPost>>.value(
value: BuyerDatabaseService().buyerPosts,
child:Scaffold(
backgroundColor: Colors.white,
appBar: header(context,isAppTitle: true),
body:Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
BuyerPostList(),
SizedBox(height: 100,),
],
),
),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => NewPost()),
);
},
label: Text(
'New',
style: TextStyle(fontWeight:FontWeight.w900,color:Color.fromRGBO(0, 0, 0, 0.4),),
),
icon: Icon(Icons.add,color:Color.fromRGBO(0, 0, 0, 0.4),),
backgroundColor:Colors.white,
),
),
);
}
}
Here is the List View BuyerPostList widget()
class BuyerPostList extends StatefulWidget {
#override
_BuyerPostListState createState() => _BuyerPostListState();
}
class _BuyerPostListState extends State<BuyerPostList> {
#override
Widget build(BuildContext context) {
final posts = Provider.of<List<BuyerPost>>(context) ?? [];
return ListView.builder(
shrinkWrap: true,
itemCount: posts.length,
itemBuilder: (context, index) {
return BuyerPostTile(post: posts[index]);
},
);
}
}
I hope i've been clear enough by my explanation. How will i make it scrollable?.
Thanks in advance.

Add physics: NeverScrollableScrollPhysics(), inside ListView.builder(
Code:
#override
Widget build(BuildContext context) {
final posts = Provider.of<List<BuyerPost>>(context) ?? [];
return ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: posts.length,
itemBuilder: (context, index) {
return BuyerPostTile(post: posts[index]);
},
);
}

Related

I want to scroll up after the all childs of ListView have been scrolled up, parent widget of listview is SingleChildScrollView in flutter

I have SingleChildScrollView as a parent and in that, I have two listviews each list view is wrapped with SizedBox with a specific height (like 700), what I want is, when I scroll up all the views that are in the first list, the first Listview should scroll up and then I'll be able to scroll next Listview, Please have a look into the code below.
Your help means a lot to me.
Thank you in advance.
Note: I'm getting this required behavior in chrome but not on a mobile device
SingleChildScrollView( child: Column(children: [
SizedBox(
height: 700,
child:ListView.builder(
itemCount:
20, itemBuilder: (context, index) {
return const ListTile(leading: Icon(Icons.icecream,
color: Colors.amber,), title: Text("Ice Cream"),);
},),
),
SizedBox(
height: 300,
child: ListView.builder(
itemCount: 20, itemBuilder: (context, index) {
return const ListTile(
leading: Icon(Icons.cake, color: Colors.red,),
title: Text("Cake"),);
},),
),
],),)
You Can Do something like this on the Controllers:
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ScrollingBehaviourInDart extends StatefulWidget {
const ScrollingBehaviourInDart({Key? key}) : super(key: key);
#override
State<ScrollingBehaviourInDart> createState() =>
_ScrollingBehaviourInDartState();
}
class _ScrollingBehaviourInDartState extends State<ScrollingBehaviourInDart> {
late ScrollController _sc1;
late ScrollController _sc2;
late ScrollController _sc3;
#override
void initState() {
_sc1 = ScrollController();
_sc2 = ScrollController();
_sc3 = ScrollController();
var _pr = Provider.of<MyScrollProvider>(context, listen: false);
_sc1.addListener(() {
log("SC1::::::::::: " + _sc1.position.pixels.toString());
if (_sc1.position.pixels == _sc1.position.minScrollExtent) {
print("OK");
_pr.changePhysics(enableScrolling: true);
}
});
_sc2.addListener(() {
if (_sc2.offset == _sc2.position.maxScrollExtent) {
_pr.changePhysics(enableScrolling: false);
log("YAAA");
}
});
_sc3.addListener(() {
log("SC3::::::::::: " + _sc3.position.pixels.toString());
});
super.initState();
}
#override
void dispose() {
_sc1.dispose();
_sc2.dispose();
_sc3.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
var _size = MediaQuery.of(context).size;
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white.withOpacity(0.8),
body: SizedBox(
height: _size.height,
child: Consumer<MyScrollProvider>(
builder: (context, myScrollProvider, _) => SingleChildScrollView(
controller: _sc1,
child: Column(
children: [
SizedBox(
height: _size.height * 0.5,
child: ListView.builder(
controller: _sc2,
physics: myScrollProvider.enablePrimaryScroll
? const AlwaysScrollableScrollPhysics()
: const NeverScrollableScrollPhysics(),
itemCount: 20,
shrinkWrap: true,
itemBuilder: (context, index) {
return const ListTile(
leading: Icon(
Icons.icecream,
color: Colors.amber,
),
title: Text("Ice Cream"),
);
},
),
),
ListView.builder(
itemCount: 20,
controller: _sc3,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return const ListTile(
leading: Icon(
Icons.cake,
color: Colors.red,
),
title: Text("Cake"),
);
},
),
],
),
),
),
),
),
);
}
}
class MyScrollProvider extends ChangeNotifier {
var enablePrimaryScroll = true;
changePhysics({required bool enableScrolling}) {
enablePrimaryScroll = enableScrolling;
notifyListeners();
}
}
maybe you can use Stickyheader.
import 'package:sticky_headers/sticky_headers.dart';
ListView(
shrinkwarp:true,
children:[
StickyHeader(
head: Text('List 1 '),
content : ListView.builder(
physics: const ClampingScrollPhysics(), // use this for clamping scroll
itemBuilder: (context, idx) => Container(),
itemCount:5,
)
StickyHeader(
head: Text('List 2 '),
content : ListView.builder(
physics: const ClampingScrollPhysics(), // use this for clamping scroll
itemBuilder: (context, idx) => Container(),
itemCount:5,
)
]
}
There are many easy ways to handle this situation as stated by many other developers. I have created an Example class with ScrollController and AbsordPointer classes to achieve the required behavior.
Sample
class Example extends StatefulWidget {
const Example({super.key});
#override
State<Example> createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
late ScrollController scrollController;
var reachedAtEnd = false;
#override
void initState() {
super.initState();
scrollController =ScrollController()..addListener(() {
if (scrollController.position.pixels == scrollController.position.maxScrollExtent) {
reachedAtEnd = true;
setState(() {
});
}
},);
}
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
physics: NeverScrollableScrollPhysics(),
child: Column(
children: [
SizedBox(
height: 700,
child: ListView.builder(
controller: scrollController,
itemCount: 20,
itemBuilder: (context, index) {
return const ListTile(
leading: Icon(
Icons.icecream,
color: Colors.amber,
),
title: Text("Ice Cream"),
);
},
),
),
SizedBox(
height: 300,
child: AbsorbPointer(
absorbing: !reachedAtEnd,
child: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return const ListTile(
leading: Icon(
Icons.cake,
color: Colors.red,
),
title: Text("Cake"),
);
},
),
),
),
],
),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
// this variable determnines whether the back-to-top button is shown or not
bool _showBackToTopButton = false;
// scroll controller
late ScrollController _scrollController;
#override
void initState() {
_scrollController = ScrollController()
..addListener(() {
setState(() {
print(_scrollController.offset);
if (_scrollController.offset >= 400) {
_showBackToTopButton = true;
// _scrollToTop();
// show the back-to-top button
} else {
_showBackToTopButton = false; // hide the back-to-top button
}
});
});
super.initState();
}
#override
void dispose() {
_scrollController.dispose(); // dispose the controller
super.dispose();
}
// This function is triggered when the user presses the back-to-top button
void _scrollToTop() {
_scrollController.animateTo(0,
duration: const Duration(seconds: 3), curve: Curves.linear);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('com'),
),
body: ListView.builder(
controller: _scrollController,
itemCount: 40,
itemBuilder: (context, index) {
print(index);
if (index == 39) {
_scrollToTop();
}
return const ListTile(
leading: Icon(
Icons.icecream,
color: Colors.amber,
),
title: Text(' Ice Cream'),
);
},
),
);
}
}

How to insert Listview.Builder in Listview.Builder item

Parent Code
how to insert my listviewBuilder in listViewBuilder item
this is my parent code
Expanded(
child: Container(
padding: EdgeInsets.only(top: 10.0),
decoration: Ui.getBoxDecoration(),
child: ListView.separated(
itemBuilder: (context, index) {
var _comment =
controller.commentWithDetailDtoList.elementAt(index);
return TimelineCommentItemWidget(comment: _comment);
},
separatorBuilder: (context, index) => SizedBox(height: 10.0),
itemCount: controller.commentWithDetailDtoList.length,
),
),
)
Child Code
and this is my child code
Visibility(
child: ListView.separated(
itemBuilder: (context, index) {
var reply = comment.replies.elementAt(index);
return TimelineCommentRepliesItemWidget(comment: reply);
},
separatorBuilder: (context, index) => SizedBox(height: 10.0),
itemCount: comment.replies.length,
),
),
Here is the code.
Please check this out.
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(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ListView.separated(itemBuilder : (BuildContext context , int i) {
return _innerWidget();
} , itemCount : 2 , shrinkWrap: true,separatorBuilder: (context, index) => SizedBox(height: 10.0), );
}
}
Widget _innerWidget(){
return ListView.builder(itemBuilder : (BuildContext context , int i) {
return Text('hello');
}, itemCount: 2,shrinkWrap: true, physics: NeverScrollableScrollPhysics(),);
}

Can't access scrollcontroller in Listview under SingleChildScrollView

I'm unable to access the scrollContoller in the ListView.builder. I think its because it's below SingleChildScrollView (when I remove SingleChildScrollView I start getting print statements from the listener attached to the scrollController ). I need to access the offset from scrollController in the ListView.builder but not sure how to do so. Here's a minimum example. How would I get the listener printing from the controller in the listView..
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
ScrollController scrollController = ScrollController();
#override
void initState() {
scrollController.addListener(() {
print("Why am I not getting print statements....");
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
height: 400,
color: Colors.orange,
),
ListView.builder(
controller: scrollController,
physics: ScrollPhysics(),
shrinkWrap: true,
itemCount: 30,
itemBuilder: (context, index) {
return Container(
color: Colors.primaries[index % Colors.primaries.length].withOpacity(0.5),
child: ListTile(
title: Text('Item $index'),
),
);
},
),
],
),
),
);
}
}
void main() {
runApp(MaterialApp(home: HomePage()));
}

Animated List Multiple widgets used the same GlobalKey

I'm trying to use a GlobalKey for an AnimatedList, so I create an animation.
But regardless where I declare the Globalkey (Inside StatelessWidget, Global, static in class), I always get the duplicated Key error.
What am I doing wrong?
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Navigation Basics',
home: Scaffold(body: FirstRoute()),
));
}
class Keys {
static GlobalKey<AnimatedListState> favoriteDrink =
GlobalKey<AnimatedListState>(debugLabel: "TestKey");
}
class FirstRoute extends StatelessWidget {
final List<String> texte = [
"Hello",
"Hello1",
"Hello2",
"Hello3",
"Hello4",
"Hello5"
];
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Center(
child: CustomListview(
texts: texte,
key: Keys.favoriteDrink,
)),
);
}
}
class CustomListview extends StatelessWidget {
final List<String> texts;
final GlobalKey<AnimatedListState> key;
CustomListview({this.texts, this.key});
#override
Widget build(BuildContext context) {
return AnimatedList(
key: key,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemBuilder: (context, index, animation) {
return Text(
texts[index],
textAlign: TextAlign.center,
);
},
initialItemCount: texts.length,
);
}
}
I solved my question.
You can't name the custom key "key". This will lead to problems.
If you rename it to something like "customKey" it will work.
class CustomListview extends StatelessWidget {
final List<String> texts;
final GlobalKey<AnimatedListState> customKey; //<--- Change this
CustomListview({this.texts, this.customKey});
#override
Widget build(BuildContext context) {
return AnimatedList(
key: customKey,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemBuilder: (context, index, animation) {
return Text(
texts[index],
textAlign: TextAlign.center,
);
},
initialItemCount: texts.length,
);
}
}

How to make scrollbar visible all time?

How do I make a scrollbar visible before user starts scrolling in flutter. Here is the code how I made my list
Scrollbar(
child: ListView.separated(
itemBuilder:
(ctx,index){
return ListTile(
isThreeLine: false,
dense: true,
leading: IconButton(
icon: Icon(Icons.location_on),
onPressed: null,
),
title: Text(bList[index].bName),
onTap: ()=>_homescreen(bList[index].bId,bList[index].bName,index),
);
},
separatorBuilder: (context,index) => Divider(color: Colors.black,),
itemCount: bList.length == null ? 0 : bList.length),
)
Wrapping the List inside Scrollbar I am able to see a scrollbar on scrolling. But is it possible to make scrollbar visible all time? Thanks in advance.
You can wrap your ListView with Scrollbar like below. When isAlwaysShown is true, must pass a controller that is attached to a scroll view
Scrollbar(
controller: ScrollController(),
isAlwaysShown: true,
child: ListView...
Demo: DartPad
You can use ScrollbarPainter. Then use AlwaysStoppedAnimation<double>(1.0) to make it always visible, ScrollNotification to update the scroll position.
MyScrollbar.dart
import 'package:flutter/material.dart';
const double _kScrollbarThickness = 6.0;
class MyScrollbar extends StatefulWidget {
final ScrollableWidgetBuilder builder;
final ScrollController scrollController;
const MyScrollbar({
Key key,
this.scrollController,
#required this.builder,
}) : assert(builder != null),
super(key: key);
#override
_MyScrollbarState createState() => _MyScrollbarState();
}
class _MyScrollbarState extends State<MyScrollbar> {
ScrollbarPainter _scrollbarPainter;
ScrollController _scrollController;
Orientation _orientation;
#override
void initState() {
super.initState();
_scrollController = widget.scrollController ?? ScrollController();
WidgetsBinding.instance.addPostFrameCallback((_) {
_updateScrollPainter(_scrollController.position);
});
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
_scrollbarPainter = _buildMaterialScrollbarPainter();
}
#override
void dispose() {
_scrollbarPainter.dispose();
super.dispose();
}
ScrollbarPainter _buildMaterialScrollbarPainter() {
return ScrollbarPainter(
color: Theme.of(context).highlightColor.withOpacity(1.0),
textDirection: Directionality.of(context),
thickness: _kScrollbarThickness,
fadeoutOpacityAnimation: const AlwaysStoppedAnimation<double>(1.0),
padding: MediaQuery.of(context).padding,
);
}
bool _updateScrollPainter(ScrollMetrics position) {
_scrollbarPainter.update(
position,
position.axisDirection,
);
return false;
}
#override
void didUpdateWidget(MyScrollbar oldWidget) {
super.didUpdateWidget(oldWidget);
_updateScrollPainter(_scrollController.position);
}
#override
Widget build(BuildContext context) {
return OrientationBuilder(
builder: (context, orientation) {
_orientation ??= orientation;
if (orientation != _orientation) {
_orientation = orientation;
_updateScrollPainter(_scrollController.position);
}
return NotificationListener<ScrollNotification>(
onNotification: (notification) =>
_updateScrollPainter(notification.metrics),
child: CustomPaint(
painter: _scrollbarPainter,
child: widget.builder(context, _scrollController),
),
);
},
);
}
}
Usage: main.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'MyScrollbar.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: MyScrollbar(
//scrollController: ctrl, //You can assign your scroll controller here or ignore
builder: (context, scrollController) => ListView.builder(
controller: scrollController, //should scrollController from callback
itemCount: 30,
itemBuilder: (context, index) => ListTile(
title: Text("Index $index"),
),
),
),
);
}
}
Note:
If one the child in ListView widget is Stateful widget and dynamically changes its size, then the MyScrollbar may not get updated.
you can use draggable scrollbar package https://pub.dev/packages/draggable_scrollbar to achieve this.
There are many possabilitys, you can show it always by using alwaysVisibleScrollThumb: true,
Fore example you can do:
DraggableScrollbar.rrect(
controller: myScrollController,
child: ListView.builder(
controller: myScrollController,
itemCount: 1000,
itemExtent: 100.0,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.all(8.0),
child: Material(
elevation: 4.0,
borderRadius: BorderRadius.circular(4.0),
color: Colors.green[index % 9 * 100],
child: Center(
child: Text(index.toString()),
),
),
);
},
),
);
Another way of doing it, originally created from #slightfoot: https://gist.github.com/slightfoot/beb74749bf2e743a6da294b37a7dcf8d
You can reach always visible scrollbar with custom scroll paint like in the following example code:
import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.indigo,
accentColor: Colors.pinkAccent,
),
home: ExampleScreen(),
),
);
}
class ExampleScreen extends StatefulWidget {
#override
_ExampleScreenState createState() => _ExampleScreenState();
}
class _ExampleScreenState extends State<ExampleScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SingleChildScrollView With Scrollbar'),
),
body:
Container(
height: MediaQuery.of(context).size.height * 0.3,
child:
SingleChildScrollViewWithScrollbar(
scrollbarColor: Theme.of(context).accentColor.withOpacity(0.75),
scrollbarThickness: 8.0,
child: Container(
//height: 1500,
child: ListView(
shrinkWrap: true,
children: <Widget>[
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
ListTile(title: Text('Item 3')),
ListTile(title: Text('Item 4')),
ListTile(title: Text('Item 5')),
ListTile(title: Text('Item 6')),
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
ListTile(title: Text('Item 3')),
ListTile(title: Text('Item 4')),
ListTile(title: Text('Item 5')),
ListTile(title: Text('Item 6')),
],
),
),
),),
);
}
}
class SingleChildScrollViewWithScrollbar extends StatefulWidget {
const SingleChildScrollViewWithScrollbar({
Key key,
this.scrollDirection = Axis.vertical,
this.reverse = false,
this.padding,
this.primary,
this.physics,
this.controller,
this.child,
this.dragStartBehavior = DragStartBehavior.down,
this.scrollbarColor,
this.scrollbarThickness = 6.0,
}) : super(key: key);
final Axis scrollDirection;
final bool reverse;
final EdgeInsets padding;
final bool primary;
final ScrollPhysics physics;
final ScrollController controller;
final Widget child;
final DragStartBehavior dragStartBehavior;
final Color scrollbarColor;
final double scrollbarThickness;
#override
_SingleChildScrollViewWithScrollbarState createState() => _SingleChildScrollViewWithScrollbarState();
}
class _SingleChildScrollViewWithScrollbarState extends State<SingleChildScrollViewWithScrollbar> {
AlwaysVisibleScrollbarPainter _scrollbarPainter;
#override
void didChangeDependencies() {
super.didChangeDependencies();
rebuildPainter();
}
#override
void didUpdateWidget(SingleChildScrollViewWithScrollbar oldWidget) {
super.didUpdateWidget(oldWidget);
rebuildPainter();
}
void rebuildPainter() {
final theme = Theme.of(context);
_scrollbarPainter = AlwaysVisibleScrollbarPainter(
color: widget.scrollbarColor ?? theme.highlightColor.withOpacity(1.0),
textDirection: Directionality.of(context),
thickness: widget.scrollbarThickness,
);
}
#override
void dispose() {
_scrollbarPainter?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return RepaintBoundary(
child: CustomPaint(
foregroundPainter: _scrollbarPainter,
child: RepaintBoundary(
child: SingleChildScrollView(
scrollDirection: widget.scrollDirection,
reverse: widget.reverse,
padding: widget.padding,
primary: widget.primary,
physics: widget.physics,
controller: widget.controller,
dragStartBehavior: widget.dragStartBehavior,
child: Builder(
builder: (BuildContext context) {
_scrollbarPainter.scrollable = Scrollable.of(context);
return widget.child;
},
),
),
),
),
);
}
}
class AlwaysVisibleScrollbarPainter extends ScrollbarPainter {
AlwaysVisibleScrollbarPainter({
#required Color color,
#required TextDirection textDirection,
#required double thickness,
}) : super(
color: color,
textDirection: textDirection,
thickness: thickness,
fadeoutOpacityAnimation: const AlwaysStoppedAnimation(1.0),
);
ScrollableState _scrollable;
ScrollableState get scrollable => _scrollable;
set scrollable(ScrollableState value) {
_scrollable?.position?.removeListener(_onScrollChanged);
_scrollable = value;
_scrollable?.position?.addListener(_onScrollChanged);
_onScrollChanged();
}
void _onScrollChanged() {
update(_scrollable.position, _scrollable.axisDirection);
}
#override
void dispose() {
_scrollable?.position?.removeListener(notifyListeners);
super.dispose();
}
}
Switch to flutter branch master
Add isAlwaysShown: true in Scrollbar
Ref
wrap your widget in Scrollbar widget
For Scrollbar or RawScrollbar visible all time, use thumbVisibility: true (isAlwaysShown: true is deprecated)
By using Scrollbar For Custom Scroll Bar,
**ScrollController controller = ScrollController(); // Mandatory: ScrollController**
Scrollbar(
controller: controller, // Mandatory: ScrollController
// isAlwaysShown: true, // deprecated
thumbVisibility: true, // For always showing Scroll Bar: Use this
thickness: 10, // Optional: Thickness
radius: Radius.circular(5), // Optional: Radius
child: ListView.builder(
itemCount: 100,
controller: controller, // Mandatory: ScrollController
itemBuilder: (context, index){
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.deepOrangeAccent,
child: FlutterLogo(),
),
title: Text('Title-$index'),
subtitle: Text('Subtitle-$index'),
trailing: CircleAvatar(
child: Icon(Icons.navigate_next),
backgroundColor: Colors.deepOrangeAccent,
),
);
},
),
),
By using RawScrollbar For Custom Scroll Bar,
ScrollController controller = ScrollController(); // Mandatory: ScrollController
RawScrollbar(
controller: controller, // Mandatory: ScrollController
// isAlwaysShown: true, // deprecated
thumbVisibility: true, // For always showing Scroll Bar: Use this
thickness: 10, // Optional: Thickness
thumbColor: Colors.greenAccent, // Optional: Color
radius: Radius.circular(5), // Optional: Radius
child: ListView.builder(
itemCount: 100,
controller: controller, // Mandatory: ScrollController
itemBuilder: (context, index){
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.deepOrangeAccent,
child: FlutterLogo(),
),
title: Text('Title-$index'),
subtitle: Text('Subtitle-$index'),
trailing: CircleAvatar(
child: Icon(Icons.navigate_next),
backgroundColor: Colors.deepOrangeAccent,
),
);
},
),
)