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.