mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This fixes some theoretical bugs whereby we were using hashCode to try
to get unique keys for objects, but really we wanted object identity.
It also lays the groundwork for a new GlobalKey concept.
I tried to keep the impact on the code minimal, which is why the "Key"
constructor is actually a factory that returns a StringKey. The code
has this class hierarchy:
```
KeyBase
|
Key--------------+---------------+
| | |
StringKey ObjectKey UniqueKey
```
...where the constructors are Key and Key.stringify (StringKey),
Key.fromObjectIdentity (ObjectKey), and Key.unique (UniqueKey).
We could instead of factory methods use regular constructors with the
following hierarchy:
```
KeyBase
|
LocalKey---------+---------------+
| | |
Key ObjectIdentityKey UniqueKey
```
...with constructors Key, Key.stringify, ObjectIdentityKey, and
UniqueKey, but I felt that that was maybe a more confusing hierarchy.
I don't have a strong opinion on this.
88 lines
2.3 KiB
Dart
88 lines
2.3 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 'dart:sky' as sky;
|
|
|
|
import 'package:sky/animation/animated_value.dart';
|
|
import 'package:sky/animation/animation_performance.dart';
|
|
import 'package:sky/animation/curves.dart';
|
|
import 'package:sky/widgets/animated_component.dart';
|
|
import 'package:sky/widgets/basic.dart';
|
|
|
|
typedef void ValueChanged(value);
|
|
|
|
const Duration _kCheckDuration = const Duration(milliseconds: 200);
|
|
|
|
abstract class Toggleable extends AnimatedComponent {
|
|
|
|
Toggleable({
|
|
Key key,
|
|
this.value,
|
|
this.onChanged
|
|
}) : super(key: key);
|
|
|
|
bool value;
|
|
ValueChanged onChanged;
|
|
|
|
AnimatedValue<double> _position;
|
|
AnimatedValue<double> get position => _position;
|
|
|
|
AnimationPerformance _performance;
|
|
AnimationPerformance get performance => _performance;
|
|
|
|
void initState() {
|
|
_position = new AnimatedValue<double>(0.0, end: 1.0);
|
|
_performance = new AnimationPerformance()
|
|
..variable = position
|
|
..duration = _kCheckDuration
|
|
..progress = value ? 1.0 : 0.0;
|
|
watch(performance);
|
|
}
|
|
|
|
void syncFields(Toggleable source) {
|
|
onChanged = source.onChanged;
|
|
if (value != source.value) {
|
|
value = source.value;
|
|
// TODO(abarth): Setting the curve on the position means there's a
|
|
// discontinuity when we reverse the timeline.
|
|
if (value) {
|
|
position.curve = curveUp;
|
|
performance.play();
|
|
} else {
|
|
position.curve = curveDown;
|
|
performance.reverse();
|
|
}
|
|
}
|
|
super.syncFields(source);
|
|
}
|
|
|
|
void _handleClick(sky.Event e) {
|
|
onChanged(!value);
|
|
}
|
|
|
|
// Override these to draw yourself
|
|
void customPaintCallback(sky.Canvas canvas, Size size);
|
|
Size get size;
|
|
|
|
EdgeDims get margin => const EdgeDims.symmetric(horizontal: 5.0);
|
|
double get duration => 200.0;
|
|
Curve get curveUp => easeIn;
|
|
Curve get curveDown => easeOut;
|
|
|
|
Widget build() {
|
|
return new Listener(
|
|
child: new Container(
|
|
margin: margin,
|
|
width: size.width,
|
|
height: size.height,
|
|
child: new CustomPaint(
|
|
token: position.value,
|
|
callback: customPaintCallback
|
|
)
|
|
),
|
|
onGestureTap: _handleClick
|
|
);
|
|
}
|
|
}
|