Commit c0536ff7 authored by Adam Barth's avatar Adam Barth

Allow customizing of Switch thumbs

Fixes #2621
parent 54d93395
...@@ -14,11 +14,19 @@ import 'theme.dart'; ...@@ -14,11 +14,19 @@ import 'theme.dart';
import 'toggleable.dart'; import 'toggleable.dart';
class Switch extends StatelessWidget { class Switch extends StatelessWidget {
Switch({ Key key, this.value, this.activeColor, this.onChanged }) Switch({
: super(key: key); Key key,
this.value,
this.activeColor,
this.activeThumbDecoration,
this.inactiveThumbDecoration,
this.onChanged
}) : super(key: key);
final bool value; final bool value;
final Color activeColor; final Color activeColor;
final Decoration activeThumbDecoration;
final Decoration inactiveThumbDecoration;
final ValueChanged<bool> onChanged; final ValueChanged<bool> onChanged;
@override @override
...@@ -44,6 +52,8 @@ class Switch extends StatelessWidget { ...@@ -44,6 +52,8 @@ class Switch extends StatelessWidget {
value: value, value: value,
activeColor: activeThumbColor, activeColor: activeThumbColor,
inactiveColor: inactiveThumbColor, inactiveColor: inactiveThumbColor,
activeThumbDecoration: activeThumbDecoration,
inactiveThumbDecoration: inactiveThumbDecoration,
activeTrackColor: activeTrackColor, activeTrackColor: activeTrackColor,
inactiveTrackColor: inactiveTrackColor, inactiveTrackColor: inactiveTrackColor,
onChanged: onChanged onChanged: onChanged
...@@ -57,6 +67,8 @@ class _SwitchRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -57,6 +67,8 @@ class _SwitchRenderObjectWidget extends LeafRenderObjectWidget {
this.value, this.value,
this.activeColor, this.activeColor,
this.inactiveColor, this.inactiveColor,
this.activeThumbDecoration,
this.inactiveThumbDecoration,
this.activeTrackColor, this.activeTrackColor,
this.inactiveTrackColor, this.inactiveTrackColor,
this.onChanged this.onChanged
...@@ -65,6 +77,8 @@ class _SwitchRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -65,6 +77,8 @@ class _SwitchRenderObjectWidget extends LeafRenderObjectWidget {
final bool value; final bool value;
final Color activeColor; final Color activeColor;
final Color inactiveColor; final Color inactiveColor;
final Decoration activeThumbDecoration;
final Decoration inactiveThumbDecoration;
final Color activeTrackColor; final Color activeTrackColor;
final Color inactiveTrackColor; final Color inactiveTrackColor;
final ValueChanged<bool> onChanged; final ValueChanged<bool> onChanged;
...@@ -74,6 +88,8 @@ class _SwitchRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -74,6 +88,8 @@ class _SwitchRenderObjectWidget extends LeafRenderObjectWidget {
value: value, value: value,
activeColor: activeColor, activeColor: activeColor,
inactiveColor: inactiveColor, inactiveColor: inactiveColor,
activeThumbDecoration: activeThumbDecoration,
inactiveThumbDecoration: inactiveThumbDecoration,
activeTrackColor: activeTrackColor, activeTrackColor: activeTrackColor,
inactiveTrackColor: inactiveTrackColor, inactiveTrackColor: inactiveTrackColor,
onChanged: onChanged onChanged: onChanged
...@@ -85,6 +101,8 @@ class _SwitchRenderObjectWidget extends LeafRenderObjectWidget { ...@@ -85,6 +101,8 @@ class _SwitchRenderObjectWidget extends LeafRenderObjectWidget {
..value = value ..value = value
..activeColor = activeColor ..activeColor = activeColor
..inactiveColor = inactiveColor ..inactiveColor = inactiveColor
..activeThumbDecoration = activeThumbDecoration
..inactiveThumbDecoration = inactiveThumbDecoration
..activeTrackColor = activeTrackColor ..activeTrackColor = activeTrackColor
..inactiveTrackColor = inactiveTrackColor ..inactiveTrackColor = inactiveTrackColor
..onChanged = onChanged; ..onChanged = onChanged;
...@@ -103,25 +121,47 @@ class _RenderSwitch extends RenderToggleable { ...@@ -103,25 +121,47 @@ class _RenderSwitch extends RenderToggleable {
bool value, bool value,
Color activeColor, Color activeColor,
Color inactiveColor, Color inactiveColor,
Decoration activeThumbDecoration,
Decoration inactiveThumbDecoration,
Color activeTrackColor, Color activeTrackColor,
Color inactiveTrackColor, Color inactiveTrackColor,
ValueChanged<bool> onChanged ValueChanged<bool> onChanged
}) : super( }) : _activeThumbDecoration = activeThumbDecoration,
value: value, _inactiveThumbDecoration = inactiveThumbDecoration,
activeColor: activeColor, _activeTrackColor = activeTrackColor,
inactiveColor: inactiveColor, _inactiveTrackColor = inactiveTrackColor,
onChanged: onChanged, super(
minRadialReactionRadius: _kThumbRadius, value: value,
size: const Size(_kSwitchWidth, _kSwitchHeight) activeColor: activeColor,
) { inactiveColor: inactiveColor,
_activeTrackColor = activeTrackColor; onChanged: onChanged,
_inactiveTrackColor = inactiveTrackColor; minRadialReactionRadius: _kThumbRadius,
size: const Size(_kSwitchWidth, _kSwitchHeight)
) {
_drag = new HorizontalDragGestureRecognizer() _drag = new HorizontalDragGestureRecognizer()
..onStart = _handleDragStart ..onStart = _handleDragStart
..onUpdate = _handleDragUpdate ..onUpdate = _handleDragUpdate
..onEnd = _handleDragEnd; ..onEnd = _handleDragEnd;
} }
Decoration get activeThumbDecoration => _activeThumbDecoration;
Decoration _activeThumbDecoration;
void set activeThumbDecoration(Decoration value) {
if (value == _activeThumbDecoration)
return;
_activeThumbDecoration = value;
markNeedsPaint();
}
Decoration get inactiveThumbDecoration => _inactiveThumbDecoration;
Decoration _inactiveThumbDecoration;
void set inactiveThumbDecoration(Decoration value) {
if (value == _inactiveThumbDecoration)
return;
_inactiveThumbDecoration = value;
markNeedsPaint();
}
Color get activeTrackColor => _activeTrackColor; Color get activeTrackColor => _activeTrackColor;
Color _activeTrackColor; Color _activeTrackColor;
void set activeTrackColor(Color value) { void set activeTrackColor(Color value) {
...@@ -176,16 +216,24 @@ class _RenderSwitch extends RenderToggleable { ...@@ -176,16 +216,24 @@ class _RenderSwitch extends RenderToggleable {
} }
Color _cachedThumbColor; Color _cachedThumbColor;
BoxPainter _thumbPainter; BoxPainter _cachedThumbPainter;
BoxDecoration _createDefaultThumbDecoration(Color color) {
return new BoxDecoration(
backgroundColor: color,
shape: BoxShape.circle,
boxShadow: elevationToShadow[1]
);
}
@override @override
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
final Canvas canvas = context.canvas; final Canvas canvas = context.canvas;
final bool isActive = onChanged != null; final bool isActive = onChanged != null;
final double currentPosition = position.value;
Color thumbColor = isActive ? Color.lerp(inactiveColor, activeColor, position.value) : inactiveColor; Color trackColor = isActive ? Color.lerp(inactiveTrackColor, activeTrackColor, currentPosition) : inactiveTrackColor;
Color trackColor = isActive ? Color.lerp(inactiveTrackColor, activeTrackColor, position.value) : inactiveTrackColor;
// Paint the track // Paint the track
Paint paint = new Paint() Paint paint = new Paint()
...@@ -201,28 +249,33 @@ class _RenderSwitch extends RenderToggleable { ...@@ -201,28 +249,33 @@ class _RenderSwitch extends RenderToggleable {
canvas.drawRRect(trackRRect, paint); canvas.drawRRect(trackRRect, paint);
Offset thumbOffset = new Offset( Offset thumbOffset = new Offset(
offset.dx + kRadialReactionRadius + position.value * _trackInnerLength, offset.dx + kRadialReactionRadius + currentPosition * _trackInnerLength,
offset.dy + size.height / 2.0 offset.dy + size.height / 2.0
); );
paintRadialReaction(canvas, thumbOffset); paintRadialReaction(canvas, thumbOffset);
if (_cachedThumbColor != thumbColor) { BoxPainter thumbPainter;
_thumbPainter = new BoxDecoration( if (_inactiveThumbDecoration == null && _activeThumbDecoration == null) {
backgroundColor: thumbColor, Color thumbColor = isActive ? Color.lerp(inactiveColor, activeColor, currentPosition) : inactiveColor;
shape: BoxShape.circle, if (thumbColor != _cachedThumbColor || _cachedThumbPainter == null) {
boxShadow: elevationToShadow[1] _cachedThumbColor = thumbColor;
).createBoxPainter(); _cachedThumbPainter = _createDefaultThumbDecoration(thumbColor).createBoxPainter();
_cachedThumbColor = thumbColor; }
thumbPainter = _cachedThumbPainter;
} else {
Decoration startDecoration = _inactiveThumbDecoration ?? _createDefaultThumbDecoration(inactiveColor);
Decoration endDecoration = _activeThumbDecoration ?? _createDefaultThumbDecoration(isActive ? activeTrackColor : inactiveColor);
thumbPainter = Decoration.lerp(startDecoration, endDecoration, currentPosition).createBoxPainter();
} }
// The thumb contracts slightly during the animation // The thumb contracts slightly during the animation
double inset = 2.0 - (position.value - 0.5).abs() * 2.0; double inset = 2.0 - (currentPosition - 0.5).abs() * 2.0;
double radius = _kThumbRadius - inset; double radius = _kThumbRadius - inset;
Rect thumbRect = new Rect.fromLTRB(thumbOffset.dx - radius, Rect thumbRect = new Rect.fromLTRB(thumbOffset.dx - radius,
thumbOffset.dy - radius, thumbOffset.dy - radius,
thumbOffset.dx + radius, thumbOffset.dx + radius,
thumbOffset.dy + radius); thumbOffset.dy + radius);
_thumbPainter.paint(canvas, thumbRect); thumbPainter.paint(canvas, thumbRect);
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment