backup. before shop update

This commit is contained in:
2021-08-31 13:28:33 -04:00
parent c378a6203c
commit 808ffa3211
292 changed files with 51551 additions and 695 deletions

View File

@@ -0,0 +1,191 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'shop_scroll_coordinator.dart';
import 'shop_scroll_position.dart';
/// 滑动控制器
class ShopScrollController extends ScrollController {
final ShopScrollCoordinator coordinator;
/// 为可滚动小部件创建一个控制器。
/// `initialScrollOffset`和`keepScrollOffset`的值不能为null。
ShopScrollController(
this.coordinator, {
double initialScrollOffset = 0.0,
this.keepScrollOffset = true,
this.debugLabel,
}) : assert(initialScrollOffset != null),
assert(keepScrollOffset != null),
_initialScrollOffset = initialScrollOffset;
/// 用于[offset]的初始值。
/// 如果[keepScrollOffset]为false或尚未保存滚动偏移量
/// 则创建并附加到此控制器的新[ScrollPosition]对象的偏移量将初始化为该值。
/// 默认为0.0。
double get initialScrollOffset => _initialScrollOffset;
final double _initialScrollOffset;
/// 每次滚动完成时,请使用[PageStorage]保存当前滚动[offset],如果重新创建了此控制器的可滚动内容,则将其还原。
///
/// 如果将此属性设置为false则永远不会保存滚动偏移量并且始终使用[initialScrollOffset]
/// 来初始化滚动偏移量。 如果为true默认值则第一次创建控制器的可滚动对象时将使用初始
/// 滚动偏移量,因为尚无要还原的滚动偏移量。 随后,将恢复保存的偏移,并且忽略[initialScrollOffset]。
///
/// 也可以看看:
/// * [PageStorageKey],当同一路径中出现多个滚动条时,应使用[PageStorageKey]
/// 来区分用于保存滚动偏移量的[PageStorage]位置。
final bool keepScrollOffset;
/// [toString]输出中使用的标签。 旨在帮助在调试输出中标识滚动控制器实例。
final String debugLabel;
/// The currently attached positions. 当前附加的 [positions]。
/// 这不应直接突变。 可以使用[attach]和[detach]添加和删除[ScrollPosition]对象。
@protected
Iterable<ScrollPosition> get positions => _positions;
final List<ScrollPosition> _positions = <ScrollPosition>[];
/// 是否有任何[ScrollPosition]对象已使用[attach]方法将自身附加到[ScrollController]。
///
/// 如果为false则不得调用与[ScrollPosition]交互的成员,
/// 例如[position][offset][animateTo]和[jumpTo]。
bool get hasClients => _positions.isNotEmpty;
/// 返回附加的[ScrollPosition],可以从中获取[ScrollView]的实际滚动偏移量。
///
/// Calling this is only valid when only a single position is attached.
/// 仅在仅连接一个[position]时调用此选项才有效。
ShopScrollPosition get position {
assert(_positions.isNotEmpty,
'ScrollController not attached to any scroll views.');
assert(_positions.length == 1,
'ScrollController attached to multiple scroll views.');
return _positions.single;
}
/// 可滚动小部件的当前滚动偏移量
/// 可滚动小部件的当前滚动偏移量。要求控制器仅控制一个可滚动小部件。
double get offset => position.pixels;
/// 从当前位置到给定值的位置动画。
/// 任何活动的动画都将被取消。 如果用户当前正在滚动,则该操作将被取消。
/// 返回的[Future]将在动画结束时完成,无论它是否成功完成或是否被过早中断。
///
/// 每当用户尝试手动滚动或启动其他活动,或者动画到达视口边缘并尝试过度滚动时,动画都会中断。
/// (如果[ScrollPosition]不会过度滚动,而是允许滚动超出范围,那么超出范围不会中断动画。)
///
/// 动画对视口或内容尺寸的更改无动于衷。
///
/// 一旦动画完成,如果滚动位置的值不稳定,则滚动位置将尝试开始弹道活动。
/// (例如,如果滚动超出范围,并且在这种情况下滚动位置通常会弹回)
///
/// 持续时间不能为零。 要在没有动画的情况下跳至特定值,请使用[jumpTo]。
Future<void> animateTo(
double offset, {
@required Duration duration,
@required Curve curve,
}) {
assert(_positions.isNotEmpty,
'ScrollController not attached to any scroll views.');
final List<Future<void>> animations = List<Future<void>>(_positions.length);
for (int i = 0; i < _positions.length; i += 1)
animations[i] =
_positions[i].animateTo(offset, duration: duration, curve: curve);
return Future.wait<void>(animations).then<void>((List<void> _) => null);
}
/// 将滚动位置从其当前值跳转到给定值,而不进行动画处理,也无需检查新值是否在范围内。
/// 任何活动的动画都将被取消。 如果用户当前正在滚动,则该操作将被取消。
///
/// 如果此方法更改了滚动位置,则将分派开始/更新/结束滚动通知的序列。 此方法不能生成过滚动通知。
///
/// 跳跃之后,如果数值超出范围,则立即开始弹道活动。
void jumpTo(double value) {
assert(_positions.isNotEmpty,
'ScrollController not attached to any scroll views.');
for (ScrollPosition position in List<ScrollPosition>.from(_positions))
position.jumpTo(value);
}
/// 在此控制器上注册给定位置。
/// 此函数返回后,此控制器上的[animateTo]和[jumpTo]方法将操纵给定位置。
void attach(ScrollPosition position) {
assert(!_positions.contains(position));
_positions.add(position);
position.addListener(notifyListeners);
}
/// 用此控制器注销给定位置。
/// 此函数返回后,此控制器上的[animateTo]和[jumpTo]方法将不会操纵给定位置。
void detach(ScrollPosition position) {
assert(_positions.contains(position));
position.removeListener(notifyListeners);
_positions.remove(position);
}
@override
void dispose() {
for (ScrollPosition position in _positions)
position.removeListener(notifyListeners);
super.dispose();
}
/// 创建一个[ScrollPosition]供[Scrollable]小部件使用。
///
/// 子类可以重写此功能,以自定义其控制的可滚动小部件使用的[ScrollPosition]。
/// 例如,[PageController]重写此函数以返回面向页面的滚动位置子类,
/// 该子类在可滚动窗口小部件调整大小时保持同一页面可见。
///
/// 默认情况下,返回[ScrollPositionWithSingleContext]。
/// 参数通常传递给正在创建的[ScrollPosition]
///
/// * `physics`[ScrollPhysics]的一个实例,它确定[ScrollPosition]对用户交互的反应方式,
/// 释放或甩动时如何模拟滚动等。该值不会为null。 它通常来自[ScrollView]或其他创建
/// [Scrollable]的小部件,或者(如果未提供)来自环境[ScrollConfiguration]。
/// * `context`:一个[ScrollContext],用于与拥有[ScrollPosition]的对象进行通信
/// (通常是[Scrollable]本身)。
/// * `oldPosition`: 如果这不是第一次为此[Scrollable]创建[ScrollPosition]
/// 则它将是前一个实例。 当环境已更改并且[Scrollable]需要重新创建[ScrollPosition]
/// 对象时,将使用此方法。 第一次创建[ScrollPosition]时为null。
ScrollPosition createScrollPosition(ScrollPhysics physics,
ScrollContext context, ScrollPosition oldPosition) {
return ShopScrollPosition(
coordinator: coordinator,
physics: physics,
context: context,
initialPixels: initialScrollOffset,
keepScrollOffset: keepScrollOffset,
oldPosition: oldPosition,
debugLabel: debugLabel,
);
}
@override
String toString() {
final List<String> description = <String>[];
debugFillDescription(description);
return '${describeIdentity(this)}(${description.join(", ")})';
}
/// 在给定的描述中添加其他信息,以供[toString]使用。
/// 此方法使子类更易于协调以提供高质量的[toString]实现。 [ScrollController]
/// 基类上的[toString]实现调用[debugFillDescription]来从子类中收集有用的信息,以合并到其返回值中。
/// 如果您重写了此方法,请确保通过调用`super.debugFillDescriptiondescription`来启动方法。
@mustCallSuper
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (debugLabel != null) description.add(debugLabel);
if (initialScrollOffset != 0.0)
description.add(
'initialScrollOffset: ${initialScrollOffset.toStringAsFixed(1)}, ');
if (_positions.isEmpty) {
description.add('no clients');
} else if (_positions.length == 1) {
// 实际上不列出客户端本身因为它的toString可能引用了我们。
description.add('one client, offset ${offset?.toStringAsFixed(1)}');
} else {
description.add('${_positions.length} clients');
}
}
}