///应用于《到答》的radio ///增加了下面三个参数 ///strokeWidth:外部圆的边框线宽度 ///outerRadius:外侧圆的半径 ///innerRadius:内部圆的半径 import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter/src/material/constants.dart'; import 'package:flutter/src/material/debug.dart'; import 'package:flutter/src/material/material_state.dart'; import 'package:flutter/src/material/theme.dart'; import 'package:flutter/src/material/theme_data.dart'; import 'package:flutter/src/material/toggleable.dart'; class DDRadio<T> extends StatefulWidget { const DDRadio({ Key key, @required this.value, @required this.groupValue, @required this.onChanged, this.mouseCursor, this.toggleable = false, this.activeColor, this.focusColor, this.hoverColor, this.materialTapTargetSize, this.visualDensity, this.focusNode, this.autofocus = false, this.strokeWidth = 1, this.outerRadius = 8, this.innerRadius = 4.5, }) : assert(autofocus != null), assert(toggleable != null), super(key: key); /// The value represented by this radio button. final T value; final T groupValue; final ValueChanged<T> onChanged; final MouseCursor mouseCursor; final bool toggleable; final Color activeColor; final MaterialTapTargetSize materialTapTargetSize; final VisualDensity visualDensity; /// The color for the radio's [Material] when it has the input focus. final Color focusColor; /// The color for the radio's [Material] when a pointer is hovering over it. final Color hoverColor; /// {@macro flutter.widgets.Focus.focusNode} final FocusNode focusNode; /// {@macro flutter.widgets.Focus.autofocus} final bool autofocus; final double strokeWidth; final double outerRadius; final double innerRadius; @override _DDRadioState<T> createState() => _DDRadioState<T>(); } class _DDRadioState<T> extends State<DDRadio<T>> with TickerProviderStateMixin { bool get enabled => widget.onChanged != null; Map<Type, Action<Intent>> _actionMap; @override void initState() { super.initState(); _actionMap = <Type, Action<Intent>>{ ActivateIntent: CallbackAction<ActivateIntent>( onInvoke: _actionHandler, ), }; } void _actionHandler(ActivateIntent intent) { if (widget.onChanged != null) { widget.onChanged(widget.value); } final RenderObject renderObject = context.findRenderObject(); renderObject.sendSemanticsEvent(const TapSemanticEvent()); } bool _focused = false; void _handleHighlightChanged(bool focused) { if (_focused != focused) { setState(() { _focused = focused; }); } } bool _hovering = false; void _handleHoverChanged(bool hovering) { if (_hovering != hovering) { setState(() { _hovering = hovering; }); } } Color _getInactiveColor(ThemeData themeData) { return enabled ? themeData.unselectedWidgetColor : themeData.disabledColor; } void _handleChanged(bool selected) { if (selected == null) { widget.onChanged(null); return; } if (selected) { widget.onChanged(widget.value); } } @override Widget build(BuildContext context) { assert(debugCheckHasMaterial(context)); final ThemeData themeData = Theme.of(context); Size size; switch (widget.materialTapTargetSize ?? themeData.materialTapTargetSize) { case MaterialTapTargetSize.padded: size = const Size(2 * kRadialReactionRadius + 8.0, 2 * kRadialReactionRadius + 8.0); break; case MaterialTapTargetSize.shrinkWrap: size = const Size(2 * kRadialReactionRadius, 2 * kRadialReactionRadius); break; } size += (widget.visualDensity ?? themeData.visualDensity).baseSizeAdjustment; final BoxConstraints additionalConstraints = BoxConstraints.tight(size); final bool selected = widget.value == widget.groupValue; final MouseCursor effectiveMouseCursor = MaterialStateProperty.resolveAs<MouseCursor>( widget.mouseCursor ?? MaterialStateMouseCursor.clickable, <MaterialState>{ if (!enabled) MaterialState.disabled, if (_hovering) MaterialState.hovered, if (_focused) MaterialState.focused, if (selected) MaterialState.selected, }, ); return FocusableActionDetector( actions: _actionMap, focusNode: widget.focusNode, autofocus: widget.autofocus, mouseCursor: effectiveMouseCursor, enabled: enabled, onShowFocusHighlight: _handleHighlightChanged, onShowHoverHighlight: _handleHoverChanged, child: Builder( builder: (BuildContext context) { return _RadioRenderObjectWidget( selected: selected, activeColor: widget.activeColor ?? themeData.toggleableActiveColor, inactiveColor: _getInactiveColor(themeData), focusColor: widget.focusColor ?? themeData.focusColor, hoverColor: widget.hoverColor ?? themeData.hoverColor, onChanged: enabled ? _handleChanged : null, toggleable: widget.toggleable, additionalConstraints: additionalConstraints, vsync: this, hasFocus: _focused, hovering: _hovering, strokeWidth: widget.strokeWidth, outerRadius: widget.outerRadius, innerRadius: widget.innerRadius, ); }, ), ); } } class _RadioRenderObjectWidget extends LeafRenderObjectWidget { const _RadioRenderObjectWidget({ Key key, @required this.selected, @required this.activeColor, @required this.inactiveColor, @required this.focusColor, @required this.hoverColor, @required this.additionalConstraints, this.onChanged, @required this.toggleable, @required this.vsync, @required this.hasFocus, @required this.hovering, @required this.strokeWidth, @required this.outerRadius, @required this.innerRadius, }) : assert(selected != null), assert(activeColor != null), assert(inactiveColor != null), assert(vsync != null), assert(toggleable != null), super(key: key); final bool selected; final bool hasFocus; final bool hovering; final Color inactiveColor; final Color activeColor; final Color focusColor; final Color hoverColor; final ValueChanged<bool> onChanged; final bool toggleable; final TickerProvider vsync; final BoxConstraints additionalConstraints; final double strokeWidth; final double outerRadius; final double innerRadius; @override _RenderRadio createRenderObject(BuildContext context) => _RenderRadio( value: selected, activeColor: activeColor, inactiveColor: inactiveColor, focusColor: focusColor, hoverColor: hoverColor, onChanged: onChanged, tristate: toggleable, vsync: vsync, additionalConstraints: additionalConstraints, hasFocus: hasFocus, hovering: hovering, strokeWidth: strokeWidth, outerRadius: outerRadius, innerRadius: innerRadius, ); @override void updateRenderObject(BuildContext context, _RenderRadio renderObject) { renderObject ..value = selected ..activeColor = activeColor ..inactiveColor = inactiveColor ..focusColor = focusColor ..hoverColor = hoverColor ..onChanged = onChanged ..tristate = toggleable ..additionalConstraints = additionalConstraints ..vsync = vsync ..hasFocus = hasFocus ..hovering = hovering ..strokeWidth = strokeWidth ..outerRadius = outerRadius ..innerRadius = innerRadius; } } class _RenderRadio extends RenderToggleable { _RenderRadio({ bool value, Color activeColor, Color inactiveColor, Color focusColor, Color hoverColor, ValueChanged<bool> onChanged, bool tristate, BoxConstraints additionalConstraints, @required TickerProvider vsync, bool hasFocus, bool hovering, @required this.strokeWidth, @required this.outerRadius, @required this.innerRadius, }) : super( value: value, activeColor: activeColor, inactiveColor: inactiveColor, focusColor: focusColor, hoverColor: hoverColor, onChanged: onChanged, tristate: tristate, additionalConstraints: additionalConstraints, vsync: vsync, hasFocus: hasFocus, hovering: hovering, ); double strokeWidth; double outerRadius; double innerRadius; @override void paint(PaintingContext context, Offset offset) { final Canvas canvas = context.canvas; paintRadialReaction(canvas, offset, size.center(Offset.zero)); final Offset center = (offset & size).center; final Color radioColor = onChanged != null ? activeColor : inactiveColor; // Outer circle final Paint paint = Paint() ..color = Color.lerp(inactiveColor, radioColor, position.value) ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth; canvas.drawCircle(center, outerRadius, paint); // Inner circle if (!position.isDismissed) { paint.style = PaintingStyle.fill; canvas.drawCircle(center, innerRadius * position.value, paint); } } @override void describeSemanticsConfiguration(SemanticsConfiguration config) { super.describeSemanticsConfiguration(config); config ..isInMutuallyExclusiveGroup = true ..isChecked = value == true; } }
使Flutter内置的Radio支持设置大小
猜你喜欢
转载自blog.csdn.net/gaoyp/article/details/119931803
今日推荐
周排行