diff --git a/sky/packages/sky/example/widgets/big_switch.dart b/sky/packages/sky/example/widgets/big_switch.dart index 3cc7de7df41..ac6e0a30dfe 100644 --- a/sky/packages/sky/example/widgets/big_switch.dart +++ b/sky/packages/sky/example/widgets/big_switch.dart @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets/basic.dart'; -import 'package:sky/widgets/switch.dart'; +import 'package:sky/widgets.dart'; import 'package:sky/theme/colors.dart'; import 'package:vector_math/vector_math.dart'; @@ -21,7 +20,7 @@ class BigSwitchApp extends App { scale.scale(5.0, 5.0); return new Container( child: new Switch(value: _value, onChanged: _handleOnChanged), - padding: new EdgeDims.all(5.0), + padding: new EdgeDims.all(20.0), transform: scale, decoration: new BoxDecoration( backgroundColor: Teal[600] diff --git a/sky/packages/sky/lib/base/hit_test.dart b/sky/packages/sky/lib/base/hit_test.dart index 4d769a0464c..9f784a03b92 100644 --- a/sky/packages/sky/lib/base/hit_test.dart +++ b/sky/packages/sky/lib/base/hit_test.dart @@ -10,6 +10,14 @@ enum EventDisposition { consumed, } +EventDisposition combineEventDispositions(EventDisposition left, EventDisposition right) { + if (left == EventDisposition.consumed || right == EventDisposition.consumed) + return EventDisposition.consumed; + if (left == EventDisposition.processed || right == EventDisposition.processed) + return EventDisposition.processed; + return EventDisposition.ignored; +} + abstract class HitTestTarget { EventDisposition handleEvent(sky.Event event, HitTestEntry entry); } diff --git a/sky/packages/sky/lib/painting/radial_reaction.dart b/sky/packages/sky/lib/painting/radial_reaction.dart new file mode 100644 index 00000000000..4df1e609c01 --- /dev/null +++ b/sky/packages/sky/lib/painting/radial_reaction.dart @@ -0,0 +1,81 @@ +// 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:async'; +import 'dart:sky' as sky; +import 'dart:sky' show Point, Offset, Color, Paint; + +import 'package:sky/animation/animated_value.dart'; +import 'package:sky/animation/animation_performance.dart'; +import 'package:sky/animation/curves.dart'; + +const Duration _kShowDuration = const Duration(milliseconds: 300); +const Duration _kHideDuration = const Duration(milliseconds: 200); +const Color _kOuterColor = const Color(0xFFFFFFFF); +const Color _kInnerColor = const Color(0xFFFFFFFF); +const double _kMaxOpacity = 0.2; + +int _roundOpacity(double opacity) { + return (255 * opacity).round(); +} + +class RadialReaction { + RadialReaction({ + this.center, + this.radius, + Point startPosition + }) { + _outerOpacity = new AnimatedValue(0.0, end: _kMaxOpacity, curve: easeOut); + _innerCenter = new AnimatedValue(startPosition, end: center, curve: easeOut); + _innerRadius = new AnimatedValue(0.0, end: radius, curve: easeOut); + _showPerformance = new AnimationPerformance() + ..addVariable(_outerOpacity) + ..addVariable(_innerCenter) + ..addVariable(_innerRadius) + ..duration = _kShowDuration; + + _fade = new AnimatedValue(1.0, end: 0.0, curve: easeIn); + _hidePerformance = new AnimationPerformance() + ..addVariable(_fade) + ..duration =_kHideDuration; + } + + final Point center; + final double radius; + + AnimationPerformance _showPerformance; + AnimatedValue _outerOpacity; + AnimatedValue _innerCenter; + AnimatedValue _innerRadius; + + Future _showComplete; + + AnimationPerformance _hidePerformance; + AnimatedValue _fade; + + void show() { + _showComplete = _showPerformance.forward(); + } + + Future hide() async { + await _showComplete; + await _hidePerformance.forward(); + } + + void addListener(Function listener) { + _showPerformance.addListener(listener); + _hidePerformance.addListener(listener); + } + + final Paint _outerPaint = new Paint(); + final Paint _innerPaint = new Paint(); + + void paint(sky.Canvas canvas, Offset offset) { + _outerPaint.color = _kOuterColor.withAlpha(_roundOpacity(_outerOpacity.value * _fade.value)); + canvas.drawCircle(center + offset, radius, _outerPaint); + + _innerPaint.color = _kInnerColor.withAlpha(_roundOpacity(_kMaxOpacity * _fade.value)); + canvas.drawCircle(_innerCenter.value + offset, _innerRadius.value, _innerPaint); + } +} diff --git a/sky/packages/sky/lib/widgets/basic.dart b/sky/packages/sky/lib/widgets/basic.dart index 6a996530723..08b9ba67a4f 100644 --- a/sky/packages/sky/lib/widgets/basic.dart +++ b/sky/packages/sky/lib/widgets/basic.dart @@ -19,7 +19,7 @@ import 'package:sky/rendering/stack.dart'; import 'package:sky/widgets/default_text_style.dart'; import 'package:sky/widgets/framework.dart'; -export 'package:sky/base/hit_test.dart' show EventDisposition; +export 'package:sky/base/hit_test.dart' show EventDisposition, combineEventDispositions; export 'package:sky/rendering/box.dart' show BackgroundImage, BoxConstraints, BoxDecoration, Border, BorderSide, EdgeDims; export 'package:sky/rendering/flex.dart' show FlexDirection, FlexJustifyContent, FlexAlignItems; export 'package:sky/rendering/object.dart' show Point, Offset, Size, Rect, Color, Paint, Path; diff --git a/sky/packages/sky/lib/widgets/framework.dart b/sky/packages/sky/lib/widgets/framework.dart index 2b4ba213071..5c8a99f0a58 100644 --- a/sky/packages/sky/lib/widgets/framework.dart +++ b/sky/packages/sky/lib/widgets/framework.dart @@ -13,7 +13,7 @@ import 'package:sky/rendering/box.dart'; import 'package:sky/rendering/object.dart'; import 'package:sky/rendering/sky_binding.dart'; -export 'package:sky/base/hit_test.dart' show EventDisposition; +export 'package:sky/base/hit_test.dart' show EventDisposition, combineEventDispositions; export 'package:sky/rendering/box.dart' show BoxConstraints, BoxDecoration, Border, BorderSide, EdgeDims; export 'package:sky/rendering/flex.dart' show FlexDirection; export 'package:sky/rendering/object.dart' show Point, Offset, Size, Rect, Color, Paint, Path; diff --git a/sky/packages/sky/lib/widgets/switch.dart b/sky/packages/sky/lib/widgets/switch.dart index 53464188de1..e2ce9d96319 100644 --- a/sky/packages/sky/lib/widgets/switch.dart +++ b/sky/packages/sky/lib/widgets/switch.dart @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; import 'dart:sky' as sky; +import 'package:sky/painting/radial_reaction.dart'; import 'package:sky/painting/shadows.dart'; import 'package:sky/rendering/box.dart'; import 'package:sky/rendering/object.dart'; @@ -26,6 +28,7 @@ const double _kTrackWidth = _kSwitchWidth - (_kThumbRadius - _kTrackRadius) * 2.0; const Duration _kCheckDuration = const Duration(milliseconds: 200); const Size _kSwitchSize = const Size(_kSwitchWidth + 2.0, _kSwitchHeight + 2.0); +const double _kReactionRadius = _kSwitchWidth / 2.0; class Switch extends Component { Switch({Key key, this.value, this.onChanged}) : super(key: key); @@ -72,13 +75,48 @@ class _RenderSwitch extends RenderToggleable { Color _thumbColor; Color get thumbColor => _thumbColor; - void set thumbColor(Color value) { if (value == _thumbColor) return; _thumbColor = value; markNeedsPaint(); } + RadialReaction _radialReaction; + + EventDisposition handleEvent(sky.Event event, BoxHitTestEntry entry) { + if (event is sky.PointerEvent) { + if (event.type == 'pointerdown') { + _showRadialReaction(entry.localPosition); + return combineEventDispositions(EventDisposition.processed, + super.handleEvent(event, entry)); + } + if (event.type == 'pointerup') { + _hideRadialReaction(); + return combineEventDispositions(EventDisposition.processed, + super.handleEvent(event, entry)); + } + } + return super.handleEvent(event, entry); + } + + void _showRadialReaction(Point startLocation) { + if (_radialReaction != null) + return; + _radialReaction = new RadialReaction( + center: new Point(_kSwitchSize.width / 2.0, _kSwitchSize.height / 2.0), + radius: _kReactionRadius, + startPosition: startLocation) + ..addListener(markNeedsPaint) + ..show(); + } + + Future _hideRadialReaction() async { + if (_radialReaction == null) + return; + await _radialReaction.hide(); + _radialReaction = null; + } + void paint(PaintingCanvas canvas, Offset offset) { sky.Color thumbColor = _kThumbOffColor; sky.Color trackColor = _kTrackOffColor; @@ -97,6 +135,9 @@ class _RenderSwitch extends RenderToggleable { ..setRectXY(rect, _kTrackRadius, _kTrackRadius); canvas.drawRRect(rrect, paint); + if (_radialReaction != null) + _radialReaction.paint(canvas, offset); + // Draw the raised thumb with a shadow paint.color = thumbColor; var builder = new ShadowDrawLooperBuilder();