Merge pull request #1415 from HansMuller/snap_scrolling_tests
Snap scrolling: additional tests, cleanup
This commit is contained in:
commit
d757694618
@ -70,6 +70,36 @@ class CardCollectionAppState extends State<CardCollectionApp> {
|
||||
_initCardModels();
|
||||
}
|
||||
|
||||
double _variableSizeToSnapOffset(double scrollOffset) {
|
||||
double cumulativeHeight = 0.0;
|
||||
double margins = 8.0;
|
||||
List<double> cumulativeHeights = _cardModels.map((card) {
|
||||
cumulativeHeight += card.height + margins;
|
||||
return cumulativeHeight;
|
||||
})
|
||||
.toList();
|
||||
|
||||
double offsetForIndex(int i) {
|
||||
return 12.0 + (margins + _cardModels[i].height) / 2.0 + ((i == 0) ? 0.0 : cumulativeHeights[i - 1]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < cumulativeHeights.length; i++) {
|
||||
if (cumulativeHeights[i] >= scrollOffset)
|
||||
return offsetForIndex(i);
|
||||
}
|
||||
return offsetForIndex(cumulativeHeights.length - 1);
|
||||
}
|
||||
|
||||
double _fixedSizeToSnapOffset(double scrollOffset) {
|
||||
double cardHeight = _cardModels[0].height;
|
||||
int cardIndex = (scrollOffset.clamp(0.0, cardHeight * (_cardModels.length - 1)) / cardHeight).floor();
|
||||
return 12.0 + cardIndex * cardHeight + cardHeight * 0.5;
|
||||
}
|
||||
|
||||
double _toSnapOffset(double scrollOffset) {
|
||||
return _fixedSizeCards ? _fixedSizeToSnapOffset(scrollOffset) : _variableSizeToSnapOffset(scrollOffset);
|
||||
}
|
||||
|
||||
void dismissCard(CardModel card) {
|
||||
if (_cardModels.contains(card)) {
|
||||
setState(() {
|
||||
@ -155,7 +185,7 @@ class CardCollectionAppState extends State<CardCollectionApp> {
|
||||
new DrawerHeader(child: new Text('Options')),
|
||||
buildDrawerCheckbox("Snap fling scrolls to center", _snapToCenter, _toggleSnapToCenter),
|
||||
buildDrawerCheckbox("Fixed size cards", _fixedSizeCards, _toggleFixedSizeCards),
|
||||
new DrawerDivider(),//buildDrawerSpacerItem(),
|
||||
new DrawerDivider(),
|
||||
buildDrawerRadioItem(DismissDirection.horizontal, 'action/code'),
|
||||
buildDrawerRadioItem(DismissDirection.left, 'navigation/arrow_back'),
|
||||
buildDrawerRadioItem(DismissDirection.right, 'navigation/arrow_forward'),
|
||||
@ -255,33 +285,6 @@ class CardCollectionAppState extends State<CardCollectionApp> {
|
||||
});
|
||||
}
|
||||
|
||||
double _variableSizeToSnapOffset(double scrollOffset) {
|
||||
double cumulativeHeight = 0.0;
|
||||
double margins = 8.0;
|
||||
List<double> cumulativeHeights = _cardModels.map((card) {
|
||||
cumulativeHeight += card.height + margins;
|
||||
return cumulativeHeight;
|
||||
})
|
||||
.toList();
|
||||
|
||||
for (int i = 0; i < cumulativeHeights.length; i++) {
|
||||
if (cumulativeHeights[i] >= scrollOffset)
|
||||
return 12.0 + (margins + _cardModels[i].height) / 2.0 + ((i == 0) ? 0.0 : cumulativeHeights[i - 1]);
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double _fixedSizeToSnapOffset(double scrollOffset) {
|
||||
double cardHeight = _cardModels[0].height;
|
||||
return 12.0 + (scrollOffset / cardHeight).floor() * cardHeight + cardHeight * 0.5;
|
||||
}
|
||||
|
||||
double _toSnapOffset(double scrollOffset) {
|
||||
return _fixedSizeCards ? _fixedSizeToSnapOffset(scrollOffset) : _variableSizeToSnapOffset(scrollOffset);
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
Widget cardCollection;
|
||||
|
@ -147,8 +147,9 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
|
||||
if (!endScrollOffset.isNaN) {
|
||||
double alignedScrollOffset = _alignedScrollSnapOffset(endScrollOffset);
|
||||
if (_scrollOffsetIsInBounds(alignedScrollOffset)) {
|
||||
double snapVelocity = velocity.abs() * (alignedScrollOffset - scrollOffset).sign;
|
||||
Simulation toSnapSimulation = scrollBehavior.createSnapScrollSimulation(
|
||||
scrollOffset, alignedScrollOffset, velocity);
|
||||
scrollOffset, alignedScrollOffset, snapVelocity);
|
||||
_toEndAnimation.start(toSnapSimulation);
|
||||
return;
|
||||
}
|
||||
|
@ -25,17 +25,19 @@ double snapOffsetCallback(double offset) {
|
||||
return (offset / itemExtent).floor() * itemExtent;
|
||||
}
|
||||
|
||||
Widget buildScrollableList() {
|
||||
Widget buildFrame() {
|
||||
scrollableListKey = new GlobalKey();
|
||||
return new Container(
|
||||
height: itemExtent * 2.0,
|
||||
child: new ScrollableList<int>(
|
||||
key: scrollableListKey,
|
||||
snapOffsetCallback: snapOffsetCallback,
|
||||
scrollDirection: scrollDirection,
|
||||
items: [0, 1, 2, 3, 4, 5, 7, 8, 9],
|
||||
itemBuilder: buildItem,
|
||||
itemExtent: itemExtent
|
||||
return new Center(
|
||||
child: new Container(
|
||||
height: itemExtent * 2.0,
|
||||
child: new ScrollableList<int>(
|
||||
key: scrollableListKey,
|
||||
snapOffsetCallback: snapOffsetCallback,
|
||||
scrollDirection: scrollDirection,
|
||||
items: [0, 1, 2, 3, 4, 5, 7, 8, 9],
|
||||
itemBuilder: buildItem,
|
||||
itemExtent: itemExtent
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -55,33 +57,71 @@ void fling(double velocity) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
test('ScrollableList snap scrolling, fling(-800)', () {
|
||||
WidgetTester tester = new WidgetTester();
|
||||
WidgetTester tester = new WidgetTester();
|
||||
tester.pumpFrame(buildFrame());
|
||||
|
||||
tester.pumpFrame(new Center(child: buildScrollableList()));
|
||||
test('ScrollableList snap scrolling, fling(-800)', () {
|
||||
scrollOffset = 0.0;
|
||||
tester.pumpFrameWithoutChange();
|
||||
expect(scrollOffset, 0.0);
|
||||
|
||||
double t0 = 0.0;
|
||||
int dt = 1000;
|
||||
new FakeAsync().run((async) {
|
||||
fling(-800.0);
|
||||
tester.pumpFrameWithoutChange(); // Start the scheduler at 0.0
|
||||
tester.pumpFrameWithoutChange(1000.0);
|
||||
async.elapse(new Duration(seconds: 1));
|
||||
tester.pumpFrameWithoutChange(t0); // Start the scheduler at 0.0
|
||||
tester.pumpFrameWithoutChange(t0 + dt);
|
||||
async.elapse(new Duration(milliseconds: dt));
|
||||
expect(scrollOffset, closeTo(200.0, 1.0));
|
||||
});
|
||||
});
|
||||
|
||||
test('ScrollableList snap scrolling, fling(-2000)', () {
|
||||
WidgetTester tester = new WidgetTester();
|
||||
|
||||
tester.pumpFrame(new Center(child: buildScrollableList()));
|
||||
scrollOffset = 0.0;
|
||||
tester.pumpFrameWithoutChange();
|
||||
expect(scrollOffset, 0.0);
|
||||
|
||||
double t0 = 0.0;
|
||||
int dt = 1000;
|
||||
new FakeAsync().run((async) {
|
||||
fling(-2000.0);
|
||||
tester.pumpFrameWithoutChange(); // Start the scheduler at 0.0
|
||||
tester.pumpFrameWithoutChange(1000.0);
|
||||
async.elapse(new Duration(seconds: 1));
|
||||
tester.pumpFrameWithoutChange(t0); // Start the scheduler at 0.0
|
||||
tester.pumpFrameWithoutChange(t0 + dt);
|
||||
async.elapse(new Duration(milliseconds: dt));
|
||||
expect(scrollOffset, closeTo(400.0, 1.0));
|
||||
});
|
||||
});
|
||||
|
||||
test('ScrollableList snap scrolling, fling(800)', () {
|
||||
scrollOffset = 400.0;
|
||||
tester.pumpFrameWithoutChange(1000.0);
|
||||
expect(scrollOffset, 400.0);
|
||||
|
||||
double t0 = 0.0;
|
||||
int dt = 2000;
|
||||
new FakeAsync().run((async) {
|
||||
fling(800.0);
|
||||
tester.pumpFrameWithoutChange(t0); // Start the scheduler at 0.0
|
||||
tester.pumpFrameWithoutChange(t0 + dt);
|
||||
async.elapse(new Duration(milliseconds: dt));
|
||||
expect(scrollOffset, closeTo(0.0, 1.0));
|
||||
});
|
||||
});
|
||||
|
||||
test('ScrollableList snap scrolling, fling(2000)', () {
|
||||
scrollOffset = 800.0;
|
||||
tester.pumpFrameWithoutChange(1000.0);
|
||||
expect(scrollOffset, 800.0);
|
||||
|
||||
double t0 = 0.0;
|
||||
int dt = 1500;
|
||||
new FakeAsync().run((async) {
|
||||
fling(2000.0);
|
||||
tester.pumpFrameWithoutChange(t0); // Start the scheduler at 0.0
|
||||
tester.pumpFrameWithoutChange(t0 + dt);
|
||||
async.elapse(new Duration(milliseconds: dt));
|
||||
expect(scrollOffset, closeTo(200.0, 1.0));
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user