I have a list view with a custom scroll physics class that defines how I want the scrolling and spring effects of a list I have. I have managed to set the spring dampening the way I want it but I can't seem to find any settings around the making the drag heavier for the user.
What I mean by that is when the user drags I want the list to feel like it has tension so the user needs to drag further than they normally would I and I will handle the movement to the next item in the list using the custom scroll physics.
I want it to feel like a turn style at a train station. There is lots of tension you receive with your body and once you pass through the turn style resets itself to center.
List:
child: ListView.builder(
cacheExtent: MediaQuery.of(context).size.height * 2,
padding: EdgeInsets.only(top: 0),
itemExtent: constraints.maxHeight -
SizeConfig.blockSizeVertical * 40,
itemCount: channelList?.length ?? 0,
controller: _controller,
physics: _physics,
itemBuilder: (BuildContext context, int index) =>
buildList(index),
),
Custom scroll class:
import 'package:flutter/material.dart';
import 'package:flutter/physics.dart';
class CustomScrollPhysics extends ScrollPhysics {
final double itemDimension;
static final SpringDescription customSpring =
SpringDescription.withDampingRatio(
mass: 4,
stiffness: 150.0,
ratio: 2.0,
);
@override
double get dragStartDistanceMotionThreshold => 40;
@override
double get minFlingVelocity => double.infinity;
@override
double get maxFlingVelocity => double.infinity;
@override
double get minFlingDistance => double.infinity;
CustomScrollPhysics({this.itemDimension, ScrollPhysics parent})
: super(parent: parent);
@override
CustomScrollPhysics applyTo(ScrollPhysics ancestor) {
return CustomScrollPhysics(
itemDimension: itemDimension, parent: buildParent(ancestor));
}
double _getPage(ScrollPosition position) {
return position.pixels / itemDimension;
}
double _getPixels(double page) {
return page * itemDimension;
}
double _getTargetPixels(
ScrollPosition position, Tolerance tolerance, double velocity) {
double page = _getPage(position);
if (velocity < -tolerance.velocity) {
page -= 0.01;
} else if (velocity > tolerance.velocity) {
page += 0.01;
}
return _getPixels(page.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 an item 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(
customSpring, position.pixels, target, velocity,
tolerance: tolerance);
}
return null;
}
@override
bool get allowImplicitScrolling => false;
}
/// Note: This Widget creates the ballistics model for a snap-to physics in a ListView.
/// Normally you might use the ListViewScrollView, however that widget currently
/// has a bug that prevents onTap detection of child widgets.
The list is centered on the screen and roughly 60% of the view height.
BouncingScrollPhysics class Null safety. Scroll physics for environments that allow the scroll offset to go beyond the bounds of the content, but then bounce the content back to the edge of those bounds. This is the behavior typically seen on iOS.
If you only need to display one item in the list at a time and the rendering of an item will fit on the screen, using a PageView widget might give you the effect that you are after.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With