mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

This CL changes how events work in fn. Previously, event listeners were passed in as constructor arguments. Now Nodes hold an |events| object, which contains all the event registrations. When a Component renders, all its |events| are copied onto the Node it produces. When an Element syncs, it walks its |events| and adds them as event listeners on the underlying sky.Element. The net result of this change is increased flexibility in how events are registered. Now components don't need to enumerate all the possible events that they support. Instead, the parent component can listen for whatever events it likes. Also, I've cleaned up the association between DrawerAnimation and Drawer. Now the constructor for Drawer accepts an |animation| object and wires up its internal event handlers itself instead of requiring the constructor to do all the wiring. R=rafaelw@chromium.org Review URL: https://codereview.chromium.org/975863003
128 lines
2.9 KiB
Dart
128 lines
2.9 KiB
Dart
part of widgets;
|
|
|
|
abstract class FixedHeightScrollable extends Component {
|
|
|
|
static Style _style = new Style('''
|
|
overflow: hidden;
|
|
position: relative;
|
|
will-change: transform;'''
|
|
);
|
|
|
|
static Style _scrollAreaStyle = new Style('''
|
|
position:relative;
|
|
will-change: transform;'''
|
|
);
|
|
|
|
double itemHeight;
|
|
double height;
|
|
double minOffset;
|
|
double maxOffset;
|
|
|
|
double _scrollOffset = 0.0;
|
|
FlingCurve _flingCurve;
|
|
int _flingAnimationId;
|
|
|
|
FixedHeightScrollable({
|
|
Object key,
|
|
this.itemHeight,
|
|
this.height,
|
|
this.minOffset,
|
|
this.maxOffset
|
|
}) : super(key: key) {}
|
|
|
|
|
|
List<Node> renderItems(int start, int count);
|
|
|
|
Node render() {
|
|
int drawCount = (height / itemHeight).round() + 1;
|
|
double alignmentDelta = -_scrollOffset % itemHeight;
|
|
if (alignmentDelta != 0.0) {
|
|
alignmentDelta -= itemHeight;
|
|
}
|
|
|
|
double drawStart = _scrollOffset + alignmentDelta;
|
|
int itemNumber = (drawStart / itemHeight).floor();
|
|
|
|
var transformStyle =
|
|
'transform: translateY(${(alignmentDelta).toStringAsFixed(2)}px)';
|
|
|
|
var items = renderItems(itemNumber, drawCount);
|
|
|
|
return new Container(
|
|
style: _style,
|
|
children: [
|
|
new Container(
|
|
style: _scrollAreaStyle,
|
|
inlineStyle: transformStyle,
|
|
children: items
|
|
)
|
|
]
|
|
)
|
|
..events.listen('gestureflingstart', _handleFlingStart)
|
|
..events.listen('gestureflingcancel', _handleFlingCancel)
|
|
..events.listen('gesturescrollupdate', _handleScrollUpdate)
|
|
..events.listen('wheel', _handleWheel);
|
|
}
|
|
|
|
void willUnmount() {
|
|
_stopFling();
|
|
}
|
|
|
|
bool _scrollBy(double scrollDelta) {
|
|
var newScrollOffset = _scrollOffset + scrollDelta;
|
|
if (minOffset != null && newScrollOffset < minOffset) {
|
|
newScrollOffset = minOffset;
|
|
} else if (maxOffset != null && newScrollOffset > maxOffset) {
|
|
newScrollOffset = maxOffset;
|
|
}
|
|
if (newScrollOffset == _scrollOffset) {
|
|
return false;
|
|
}
|
|
|
|
setState(() {
|
|
_scrollOffset = newScrollOffset;
|
|
});
|
|
return true;
|
|
}
|
|
|
|
void _scheduleFlingUpdate() {
|
|
_flingAnimationId = sky.window.requestAnimationFrame(_updateFling);
|
|
}
|
|
|
|
void _stopFling() {
|
|
if (_flingAnimationId == null) {
|
|
return;
|
|
}
|
|
|
|
sky.window.cancelAnimationFrame(_flingAnimationId);
|
|
_flingCurve = null;
|
|
_flingAnimationId = null;
|
|
}
|
|
|
|
void _updateFling(double timeStamp) {
|
|
double scrollDelta = _flingCurve.update(timeStamp);
|
|
if (!_scrollBy(scrollDelta))
|
|
return _stopFling();
|
|
_scheduleFlingUpdate();
|
|
}
|
|
|
|
void _handleScrollUpdate(sky.Event event) {
|
|
_scrollBy(-event.dy);
|
|
}
|
|
|
|
void _handleFlingStart(sky.Event event) {
|
|
setState(() {
|
|
_flingCurve = new FlingCurve(-event.velocityY, event.timeStamp);
|
|
_scheduleFlingUpdate();
|
|
});
|
|
}
|
|
|
|
void _handleFlingCancel(sky.Event event) {
|
|
_stopFling();
|
|
}
|
|
|
|
void _handleWheel(sky.Event event) {
|
|
_scrollBy(-event.offsetY);
|
|
}
|
|
}
|