Skip to content

Instantly share code, notes, and snippets.

@bambinoua
Forked from slightfoot/always_scrollbar.dart
Created January 10, 2023 12:38
Show Gist options
  • Save bambinoua/544c2f78691fd53945d7508cc201d774 to your computer and use it in GitHub Desktop.
Save bambinoua/544c2f78691fd53945d7508cc201d774 to your computer and use it in GitHub Desktop.
Always Visible Scrollbar for Flutter - 4th March 2019
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: SingleChildScrollViewWithScrollbar(
scrollbarColor: Theme.of(context).accentColor.withOpacity(0.75),
scrollbarThickness: 8.0,
child: Container(
height: 1500,
child: Placeholder(),
),
),
);
}
}
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();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment