尝试使用 CustomPainter 选中和取消选中动画来创建 MyRadio。Drwing all...但无法从另一个元素更改无线电组中的视图状态(运行动画)。无线电代码:
import 'package:flutter/material.dart';
class MyRadio<T> extends StatefulWidget {
final T value;
final T? groupValue;
final String label;
final String text;
final ValueChanged<T?> onChanged;
final double size;
const MyRadio(
{Key? key,
required this.value,
this.groupValue,
required this.label,
required this.text,
required this.onChanged,
this.size = 20.0})
: super(key: key);
@override
State<MyRadio<T>> createState() => _MyRadioState<T>();
}
class _MyRadioState<T> extends State<MyRadio<T>> with TickerProviderStateMixin {
late Animation<double> radiusAnimation;
late Animation<double> labelAnimation;
late AnimationController radiusAnimationController;
late AnimationController labelAnimationController;
bool check() {
return (widget.groupValue != null && widget.groupValue == widget.value)
? true
: false;
}
@override
void initState() {
super.initState();
radiusAnimationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 300));
labelAnimationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 300));
Tween<double> _radiusTween = Tween(begin: widget.size, end: 0.0);
Tween<double> _labelTween = Tween(begin: 0.0, end: widget.size);
radiusAnimation = _radiusTween.animate(radiusAnimationController)
..addListener(() => setState(() {}))
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
labelAnimationController.forward();
}
if (status == AnimationStatus.dismissed) {
labelAnimationController.repeat();
}
});
labelAnimation = _labelTween.animate(labelAnimationController)
..addListener(() => setState(() {}))
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
labelAnimationController.forward();
} else if (status == AnimationStatus.dismissed) {
labelAnimationController.forward();
}
});
if (check()) {
radiusAnimationController.forward();
}
}
@override
void dispose() {
radiusAnimationController.dispose();
labelAnimationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
child: AnimatedBuilder(
builder: (context, snapshot) {
return CustomPaint(
painter: ShapePainter(
radius: radiusAnimation.value,
labelScale: labelAnimation.value),
child: Container(
decoration: BoxDecoration(border: Border.all()),
width: widget.size * 2,
height: widget.size * 2,
),
);
},
animation: radiusAnimation,
),
onTap: () {
widget.onChanged(widget.value);
if (!check()) {
radiusAnimationController.forward();
}
},
);
}
}
class ShapePainter extends CustomPainter {
final double radius;
final double labelScale;
ShapePainter({required this.labelScale, required this.radius});
@override
void paint(Canvas canvas, Size size) {
var animateBrush = Paint()
..color = Colors.white
..strokeWidth = 3
..strokeCap = StrokeCap.round;
var fillBrush = Paint()
..color = Colors.teal
..strokeWidth = 3
..strokeCap = StrokeCap.round;
var labelBrush = Paint()
..color = Colors.white
..strokeWidth = 4
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round;
Offset center = Offset(size.width / 2, size.height / 2);
canvas.drawCircle(center, size.width / 2, fillBrush);
canvas.drawCircle(center, radius - 3, animateBrush);
canvas.drawPath(_getCheckIconPath(labelScale * 2, size.width), labelBrush);
}
Path _getCheckIconPath(double s, ws) {
Path path = Path();
double size = s * 0.15;
double x = -3 / 2 * size + ws / 2;
double y = ws / 2;
path.moveTo(x, y);
path.lineTo(x + size, y + size);
path.lineTo(x + 3 * size, y - size);
return path;
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
演示代码:
import 'package:flutter/material.dart';
import 'package:testapp/ui/my_radio.dart';
class RadioDemo extends StatefulWidget {
const RadioDemo({Key? key}) : super(key: key);
@override
State createState() => _RadioDemoState();
}
class _RadioDemoState extends State<RadioDemo> {
String _groupValue = "1";
ValueChanged<String?> _valueChangedHandler() {
return (value) => setState(() => _groupValue = value!);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Test'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(_groupValue),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MyRadio<String>(
value: '1',
groupValue: _groupValue,
onChanged: _valueChangedHandler(),
label: '1',
text: 'Phone Gap',
),
const SizedBox(
width: 30,
),
MyRadio<String>(
value: '2',
groupValue: _groupValue,
onChanged: _valueChangedHandler(),
label: '2',
text: 'Appcelerator',
),
],
)
],
),
);
}
}
使用来源:https ://medium.com/flutterdevs/exploring-custom-radio-button-in-flutter-4a93a7892185
SetState 不工作!!!!