Skip to content

Instantly share code, notes, and snippets.

@MisterJimson
Created May 1, 2020 13:55
Show Gist options
  • Save MisterJimson/2bb21edc246e60bb372add446014b090 to your computer and use it in GitHub Desktop.
Save MisterJimson/2bb21edc246e60bb372add446014b090 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: Scaffold(body: MyApp())));
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ScrollController _scrollController;
@override
void initState() {
super.initState();
_scrollController = ScrollController();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: ListView.builder(
controller: _scrollController,
itemCount: 20,
itemBuilder: (context, index) =>
ListTile(title: Text(index.toString())),
),
),
ScrollAway(
maxHeight: 56,
scrollController: _scrollController,
child: Wrap(
children: <Widget>[
Container(
width: double.infinity,
height: 56,
color: Colors.grey[300],
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_buildItem(Icons.home, "Home"),
_buildItem(Icons.blur_circular, "Collection"),
_buildItem(Icons.supervised_user_circle, "Community"),
_buildItem(Icons.notifications, "Notifications"),
],
),
),
],
),
),
],
);
}
Widget _buildItem(IconData icon, String title) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, size: 28),
Text(title, style: TextStyle(fontSize: 10)),
],
);
}
}
/// Provides a way to react to scrolling for the purposes of animating away
/// part of your UI.
///
/// [maxHeight] is the height of the content you want to animate away
///
/// [onUpdate] is a callback that will give you an offset to apply to your UI
/// as the user scrolls. Try using it with an [AnimatedContainer].
///
/// For simple cases, see [ScrollAway]
class ScrollAwayController {
final ScrollController scrollController;
final void Function(double) onUpdate;
final double maxHeight;
double _delta = 0;
double _oldOffset = 0;
void Function() onScroll;
ScrollAwayController({
@required this.scrollController,
@required this.onUpdate,
@required this.maxHeight,
}) {
onScroll = () {
bool isAtBottom =
scrollController.offset >= scrollController.position.maxScrollExtent;
bool isAtTop =
scrollController.offset <= scrollController.position.minScrollExtent;
double _offset = scrollController.offset;
_delta += (_offset - _oldOffset);
if (_delta > maxHeight || isAtBottom) {
_delta = maxHeight;
} else if (_delta < 0 || isAtTop) {
_delta = 0;
}
_oldOffset = _offset;
onUpdate(-_delta);
};
scrollController.addListener(onScroll);
}
void dispose() {
scrollController.removeListener(onScroll);
}
}
/// Provides a way to react to scrolling for the purposes of animating away
/// the [child] passed in.
///
/// [maxHeight] is the height of the content you want to animate away
///
/// [scrollController] should be a [ScrollController] being used in the
/// scrollable content that you want to react to
class ScrollAway extends StatefulWidget {
final ScrollController scrollController;
final double maxHeight;
final Widget child;
const ScrollAway({
Key key,
@required this.scrollController,
@required this.maxHeight,
@required this.child,
}) : super(key: key);
@override
_ScrollAwayState createState() => _ScrollAwayState(scrollController);
}
class _ScrollAwayState extends State<ScrollAway> {
final ScrollController scrollController;
ScrollAwayController scrollAwayController;
double offset = 0;
_ScrollAwayState(this.scrollController);
@override
void initState() {
scrollAwayController = ScrollAwayController(
scrollController: scrollController,
onUpdate: (value) {
setState(() {
offset = value;
});
},
maxHeight: widget.maxHeight,
);
super.initState();
}
@override
Widget build(BuildContext context) {
return AnimatedContainer(
duration: Duration(milliseconds: 100),
height: widget.maxHeight + offset,
child: widget.child,
);
}
@override
void dispose() {
scrollAwayController.dispose();
super.dispose();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment