From 2bb268492ced2a09d450c5922f0e4e9fef78fff7 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Sun, 14 Feb 2016 17:55:49 -0800 Subject: [PATCH] Improve checkbox animation This patch improves the checkbox animation as suggested by the design team. The color transition now occurs earlier in the animation and there are fewer components to the animation. Fixes #1614 --- .../flutter/lib/src/material/checkbox.dart | 69 +++++++------------ 1 file changed, 23 insertions(+), 46 deletions(-) diff --git a/packages/flutter/lib/src/material/checkbox.dart b/packages/flutter/lib/src/material/checkbox.dart index b1fc42418e..b4330c2433 100644 --- a/packages/flutter/lib/src/material/checkbox.dart +++ b/packages/flutter/lib/src/material/checkbox.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui show Gradient; +import 'dart:math' as math; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; @@ -109,63 +109,40 @@ class _RenderCheckbox extends RenderToggleable { paintRadialReaction(canvas, offset + const Offset(kRadialReactionRadius, kRadialReactionRadius)); - // Choose a color between grey and the theme color - Paint paint = new Paint() - ..strokeWidth = _kStrokeWidth - ..color = inactiveColor; + double t = position.value; - // The rrect contracts slightly during the transition animation from checked states. - // Because we have a stroke size of 2, we should have a minimum 1.0 inset. - double inset = 2.0 - (position.value - _kMidpoint).abs() * 2.0; + Color borderColor = inactiveColor; + if (onChanged != null) + borderColor = t >= 0.25 ? activeColor : Color.lerp(inactiveColor, activeColor, t * 4.0); + + Paint paint = new Paint() + ..color = borderColor; + + double inset = 1.0 - (t - 0.5).abs() * 2.0; double rectSize = _kEdgeSize - inset * _kStrokeWidth; Rect rect = new Rect.fromLTWH(offsetX + inset, offsetY + inset, rectSize, rectSize); - // Create an inner rectangle to cover inside of rectangle. This is needed to avoid - // painting artefacts caused by overlayed paintings. - Rect innerRect = rect.deflate(1.0); - RRect rrect = new RRect.fromRectXY(rect, _kEdgeRadius, _kEdgeRadius); - // Outline of the empty rrect - paint.style = PaintingStyle.stroke; - canvas.drawRRect(rrect, paint); - - // Radial gradient that changes size - if (!position.isDismissed) { - paint - ..style = PaintingStyle.fill - ..shader = new ui.Gradient.radial( - new Point(_kEdgeSize / 2.0, _kEdgeSize / 2.0), - _kEdgeSize * (_kMidpoint - position.value) * 8.0, - [ - const Color(0x00000000), - inactiveColor - ] - ); - canvas.drawRect(innerRect, paint); - } - - if (position.value > _kMidpoint) { - double t = (position.value - _kMidpoint) / (1.0 - _kMidpoint); - - if (onChanged != null) { - // First draw a rounded rect outline then fill inner rectangle with the active color - paint - ..color = activeColor.withAlpha((t * 255).floor()) - ..style = PaintingStyle.stroke; - canvas.drawRRect(rrect, paint); - paint.style = PaintingStyle.fill; - canvas.drawRect(innerRect, paint); - } + RRect outer = new RRect.fromRectXY(rect, _kEdgeRadius, _kEdgeRadius); + if (t <= 0.5) { + // Outline + RRect inner = outer.deflate(math.min(rectSize / 2.0, _kStrokeWidth + rectSize * t)); + canvas.drawDRRect(outer, inner, paint); + } else { + // Background + canvas.drawRRect(outer, paint); // White inner check + double value = (t - 0.5) * 2.0; paint ..color = const Color(0xFFFFFFFF) - ..style = PaintingStyle.stroke; + ..style = PaintingStyle.stroke + ..strokeWidth = _kStrokeWidth; Path path = new Path(); Point start = new Point(_kEdgeSize * 0.15, _kEdgeSize * 0.45); Point mid = new Point(_kEdgeSize * 0.4, _kEdgeSize * 0.7); Point end = new Point(_kEdgeSize * 0.85, _kEdgeSize * 0.25); - Point drawStart = Point.lerp(start, mid, 1.0 - t); - Point drawEnd = Point.lerp(mid, end, t); + Point drawStart = Point.lerp(start, mid, 1.0 - value); + Point drawEnd = Point.lerp(mid, end, value); path.moveTo(offsetX + drawStart.x, offsetY + drawStart.y); path.lineTo(offsetX + mid.x, offsetY + mid.y); path.lineTo(offsetX + drawEnd.x, offsetY + drawEnd.y);