Last active
January 11, 2024 10:47
-
-
Save austinevick/d53857dc6aa02d49e19757390d953526 to your computer and use it in GitHub Desktop.
Programmatically scroll to top
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ScrollToTopWidgetWrapper extends StatefulWidget { | |
final Widget child; | |
const ScrollToTopWidgetWrapper({super.key, required this.child}); | |
@override | |
State<ScrollToTopWidgetWrapper> createState() => | |
_ScrollToTopWidgetWrapperState(); | |
} | |
class _ScrollToTopWidgetWrapperState extends State<ScrollToTopWidgetWrapper> { | |
final scrollController = ScrollController(); | |
bool isVisible = false; | |
@override | |
void initState() { | |
scrollController.addListener(_scrollListener); | |
super.initState(); | |
} | |
_scrollListener() { | |
if (scrollController.offset > 0.0) { | |
setState(() { | |
isVisible = true; | |
}); | |
} | |
if (scrollController.offset <= 0.0) { | |
setState(() { | |
isVisible = false; | |
}); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Stack( | |
children: [ | |
SingleChildScrollView( | |
controller: scrollController, child: widget.child), | |
isVisible | |
? Positioned( | |
bottom: 16, | |
right: 8, | |
child: AnimatedFloatingButton( | |
onPressed: () => scrollController.animateTo(0.0, | |
duration: Durations.long4, curve: Curves.easeInOut)), | |
) | |
: const Center() | |
], | |
); | |
} | |
} | |
class AnimatedFloatingButton extends StatefulWidget { | |
final VoidCallback onPressed; | |
const AnimatedFloatingButton({super.key, required this.onPressed}); | |
@override | |
State<AnimatedFloatingButton> createState() => _AnimatedFloatingButtonState(); | |
} | |
class _AnimatedFloatingButtonState extends State<AnimatedFloatingButton> | |
with SingleTickerProviderStateMixin { | |
late AnimationController _controller; | |
late Animation<Offset> animation; | |
@override | |
void initState() { | |
super.initState(); | |
_controller = | |
AnimationController(vsync: this, duration: const Duration(seconds: 4)); | |
animation = | |
Tween(begin: const Offset(5, 0), end: const Offset(0, 0)).animate(_controller); | |
_controller.forward(); | |
} | |
@override | |
void dispose() { | |
_controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return SlideTransition( | |
position: animation, | |
child: CustomButton( | |
color: Colors.green, | |
height: 60, | |
width: 60, | |
radius: 50, | |
onPressed: widget.onPressed, | |
child: const Icon( | |
Icons.keyboard_arrow_up, | |
size: 34, | |
color: Colors.white, | |
)), | |
); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment