Skip to content

Instantly share code, notes, and snippets.

@imaNNeo
Created October 24, 2020 19:46
Show Gist options
  • Save imaNNeo/7d28d14fc8d75bc4a7db025ddc09d6bc to your computer and use it in GitHub Desktop.
Save imaNNeo/7d28d14fc8d75bc4a7db025ddc09d6bc to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
import 'dart:math' as math;
main() => runApp(MaterialApp(home: MyHomePage()));
class MyHomePage extends StatelessWidget {
final itemWidth = 120.0;
final itemHorizontalMargin = 4.0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter 4 Fun'),
),
body: Center(
child: SizedBox(
height: 200.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
physics: SnappingListScrollPhysic(itemWidth: itemWidth + (itemHorizontalMargin * 2)),
itemBuilder: (context, i) {
return Container(
width: itemWidth,
height: 200,
margin: EdgeInsets.symmetric(horizontal: itemHorizontalMargin),
decoration: BoxDecoration(
color: Colors.purple,
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
child: Center(
child: Text(
'$i',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 22,
),
),
),
);
},
),
),
),
);
}
}
class SnappingListScrollPhysic extends ScrollPhysics {
final double itemWidth;
const SnappingListScrollPhysic({
@required this.itemWidth,
ScrollPhysics parent,
}) : super(parent: parent);
@override
SnappingListScrollPhysic applyTo(ScrollPhysics ancestor) => SnappingListScrollPhysic(
parent: buildParent(ancestor),
itemWidth: itemWidth,
);
double _getItem(ScrollPosition position) => (position.pixels) / itemWidth;
double _getPixels(ScrollPosition position, double item) =>
math.min(item * itemWidth, position.maxScrollExtent);
double _getTargetPixels(ScrollPosition position, Tolerance tolerance, double velocity) {
double item = _getItem(position);
if (velocity < -tolerance.velocity) {
item -= 0.5;
} else if (velocity > tolerance.velocity) {
item += 0.5;
}
return _getPixels(position, item.roundToDouble());
}
@override
Simulation createBallisticSimulation(ScrollMetrics position, double velocity) {
// If we're out of range and not headed back in range, defer to the parent
// ballistics, which should put us back in range at a page boundary.
if ((velocity <= 0.0 && position.pixels <= position.minScrollExtent) ||
(velocity >= 0.0 && position.pixels >= position.maxScrollExtent)) {
return super.createBallisticSimulation(position, velocity);
}
final Tolerance tolerance = this.tolerance;
final double target = _getTargetPixels(position, tolerance, velocity);
if (target != position.pixels) {
return ScrollSpringSimulation(spring, position.pixels, target, velocity,
tolerance: tolerance);
}
return null;
}
@override
bool get allowImplicitScrolling => false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment