mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This CL cleans up the sky/framework/animation as follows: 1) I've moved code that's used only by the custom elements framework into sky/framework/elements/animation. This code is based on AnimationDelegates rather than Streams. 2) Rename ScrollCurve to ScrollBehavior because it encapsulates more behavior than just a curve. 3) Make the Generator interface explicit and mark subclasses as actual subclasses. 4) Move Simulation into generators.dart because it implements the Generator interface. 5) Move Animation out of generators.dart because it does not implement the Generator interface. R=eseidel@chromium.org Review URL: https://codereview.chromium.org/1001373002
115 lines
2.9 KiB
Dart
115 lines
2.9 KiB
Dart
// Copyright 2015 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import '../animation/curves.dart';
|
|
import '../animation/fling_curve.dart';
|
|
import '../animation/generators.dart';
|
|
import '../animation/scroll_behavior.dart';
|
|
import '../animation/mechanics.dart';
|
|
import '../fn.dart';
|
|
import 'dart:sky' as sky;
|
|
|
|
abstract class Scrollable extends Component {
|
|
ScrollBehavior scrollBehavior;
|
|
double get scrollOffset => _scrollOffset;
|
|
|
|
double _scrollOffset = 0.0;
|
|
FlingCurve _flingCurve;
|
|
int _flingAnimationId;
|
|
Simulation _simulation;
|
|
|
|
Scrollable({Object key, this.scrollBehavior}) : super(key: key) {
|
|
events.listen('pointerdown', _handlePointerDown);
|
|
events.listen('pointerup', _handlePointerUpOrCancel);
|
|
events.listen('pointercancel', _handlePointerUpOrCancel);
|
|
events.listen('gestureflingstart', _handleFlingStart);
|
|
events.listen('gestureflingcancel', _handleFlingCancel);
|
|
events.listen('gesturescrollupdate', _handleScrollUpdate);
|
|
events.listen('wheel', _handleWheel);
|
|
}
|
|
|
|
void didUnmount() {
|
|
super.didUnmount();
|
|
_stopFling();
|
|
_stopSimulation();
|
|
}
|
|
|
|
bool scrollBy(double scrollDelta) {
|
|
var newScrollOffset = scrollBehavior.applyCurve(_scrollOffset, scrollDelta);
|
|
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 _stopSimulation() {
|
|
if (_simulation == null)
|
|
return;
|
|
_simulation.cancel();
|
|
_simulation = null;
|
|
}
|
|
|
|
void _updateFling(double timeStamp) {
|
|
double scrollDelta = _flingCurve.update(timeStamp);
|
|
if (!scrollBy(scrollDelta))
|
|
return _settle();
|
|
_scheduleFlingUpdate();
|
|
}
|
|
|
|
void _settle() {
|
|
_stopFling();
|
|
Particle particle = new Particle(position: scrollOffset);
|
|
_simulation = scrollBehavior.release(particle);
|
|
if (_simulation == null)
|
|
return;
|
|
_simulation.onTick.listen((_) {
|
|
setState(() {
|
|
_scrollOffset = particle.position;
|
|
});
|
|
});
|
|
}
|
|
|
|
void _handlePointerDown(_) {
|
|
_stopFling();
|
|
_stopSimulation();
|
|
}
|
|
|
|
void _handlePointerUpOrCancel(_) {
|
|
if (_flingCurve == null)
|
|
_settle();
|
|
}
|
|
|
|
void _handleScrollUpdate(sky.GestureEvent event) {
|
|
scrollBy(-event.dy);
|
|
}
|
|
|
|
void _handleFlingStart(sky.GestureEvent event) {
|
|
_stopSimulation();
|
|
_flingCurve = new FlingCurve(-event.velocityY, event.timeStamp);
|
|
_scheduleFlingUpdate();
|
|
}
|
|
|
|
void _handleFlingCancel(sky.GestureEvent event) {
|
|
_settle();
|
|
}
|
|
|
|
void _handleWheel(sky.WheelEvent event) {
|
|
scrollBy(-event.offsetY);
|
|
}
|
|
}
|