【发布时间】:2021-01-25 09:38:56
【问题描述】:
我有一个带有自定义滚动物理类的列表视图,它定义了我想要的列表的滚动和弹簧效果。我已经设法按照我想要的方式设置了弹簧阻尼,但我似乎找不到任何关于使用户的阻力更重的设置。
我的意思是当用户拖动时我希望列表感觉有张力所以用户需要比平时拖动得更远,我将处理移动到列表中的下一项使用自定义滚动物理。
我希望它感觉像在火车站的转弯风格。你的身体会受到很大的压力,一旦你通过转弯风格就会重新回到中心。
列表:
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),
),
自定义滚动类:
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.
列表居中在屏幕上,大约是视图高度的 60%。
【问题讨论】:
-
在 iOS 中,当您拖动“超出”限制时,它的行为与您描述的完全一样。我会通过简单地使用它来找到一个快速的解决方案。将您的“结束”移动到“太短”的位置,然后快速将“结束”设置为真正的结束,一旦用户实际到达结束。
-
您所描述的听起来像是设置了最大值snap(2nd acceleration derivative)。限制快照意味着更长的滚动会导致(最大)稳定增加的加速度变化率。或者,限制 jerk(第一加速度导数)或将 jerk 乘以 0 到 1 之间的因子也可能获得所需的结果。我不知道如何在颤振中实现它。
-
所以你要做的是实现速度随时间的变化,这样你就可以使用速度的导数。我不知道颤振是否已经提供了这一点,或者你是否需要自己做。