This article shares the usage method of Flutter voting component for your reference. The specific content is as follows
prospect
Based on the company's project needs, the voting function is implemented in Weibo.
Problems encountered in development
1. The height of the option list, the problem of adaptability;
2. Progress bar animation problem;
3. List recycling mechanism, resulting in repeated progress bar animation;
4. Customize the rounded corners around the progress bar;
How to solve the problem
- Get the longest data in the array list, and then calculate it according to the screen width. If there are more than one line, set the height of two lines, otherwise use the height of one line;
_didExceedOneMoreLines(String text, double width, TextStyle style) { final span = TextSpan(text: text, style: style); final tp = TextPainter(text: span, maxLines: 1, textDirection: ); (maxWidth: width); if () { //Set the height of the item option _itemHeight = ; } }
- When initializing the (initState) method of the Widget control, use the AnimationController animation and implement SingleTickerProviderStateMixin, and call _controller.animateTo() in the build method
AnimationController _controller; _controller = AnimationController( vsync: this, duration: const Duration(seconds: 1), )..addListener(() { setState(() {}); }); //Trigger animation, execution location_controller.animateTo()
- Mark the field in the list data to make it perform the animation; when the user votes successfully, change the status and execute the progress bar animation. After the user swipes the list, change the mark tofalse. Turn off the animation effect.
- For modifying some source code, set the progress bar rounded corner control;
import 'package:flutter/'; import 'package:flutter/'; import 'package:flutter/'; import 'package:flutter_screenutil/flutter_screenutil.dart'; class RoundLinearProgressPainter extends ProgressIndicator { const RoundLinearProgressPainter({ Key key, double value, Color backgroundColor, Color color, Animation<Color> valueColor, , String semanticsLabel, String semanticsValue, }) : assert(minHeight == null || minHeight > 0), super( key: key, value: value, backgroundColor: backgroundColor, color: color, valueColor: valueColor, semanticsLabel: semanticsLabel, semanticsValue: semanticsValue, ); final double minHeight; @override _RoundLinearProgressPainterState createState() => _RoundLinearProgressPainterState(); } class _RoundLinearProgressPainterState extends State<RoundLinearProgressPainter> with SingleTickerProviderStateMixin { AnimationController _controller; @override void initState() { (); _controller = AnimationController( duration: const Duration(milliseconds: 1), vsync: this, )..addListener(() { setState(() {}); }); if ( != null) _controller.forward(); } @override Widget build(BuildContext context) { return widget._buildSemanticsWrapper( context: context, child: Container( constraints: BoxConstraints( minWidth: , minHeight: ?? 4.0, ), child: CustomPaint( painter: _LinearProgressIndicatorPainter( backgroundColor: widget._getBackgroundColor(context), valueColor: widget._getValueColor(context), value: , animationValue: _controller.value, ), ), ), ); } @override void didUpdateWidget(RoundLinearProgressPainter oldWidget) { (oldWidget); if ( == null && !_controller.isAnimating) _controller.repeat(); else if ( != null && _controller.isAnimating) _controller.stop(); } @override void dispose() { _controller.dispose(); (); } } class _LinearProgressIndicatorPainter extends CustomPainter { const _LinearProgressIndicatorPainter({ , , , , }); final Color backgroundColor; final Color valueColor; final double value; final double animationValue; @override void paint(Canvas canvas, Size size) { final Paint paint = Paint() ..color = backgroundColor ..isAntiAlias = true ..style = ; ( & size, paint); = valueColor; void drawBar(double x, double width) { if (width <= 0.0) return; RRect rRect; ///Width of rounded corners var radius = (); if (value == 1.0) { /// When the progress bar is 1, set the rounded corners around rRect = ( Offset(0.0, 0.0) & Size(width, ), radius); } else { /// When it is less than 1, set the left rounded corner rRect = ( Offset(0.0, 0.0) & Size(width, ), topLeft: radius, bottomLeft: radius); } (rRect, paint); } if (value != null) { drawBar(0.0, (0.0, 1.0) * ); } } @override bool shouldRepaint(_LinearProgressIndicatorPainter oldPainter) { return != backgroundColor || != valueColor || != value || != animationValue; } } abstract class ProgressIndicator extends StatefulWidget { const ProgressIndicator({ Key key, , , , , , , }) : super(key: key); final double value; final Color backgroundColor; final Color color; final Animation<Color> valueColor; final String semanticsLabel; final String semanticsValue; Color _getBackgroundColor(BuildContext context) => backgroundColor ?? (context).; Color _getValueColor(BuildContext context) => valueColor?.value ?? color ?? (context).; @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { (properties); (PercentProperty('value', value, showName: false, ifNull: '<indeterminate>')); } Widget _buildSemanticsWrapper({ BuildContext context, Widget child, }) { String expandedSemanticsValue = semanticsValue; if (value != null) { expandedSemanticsValue ??= '${(value * 100).round()}%'; } return Semantics( label: semanticsLabel, value: expandedSemanticsValue, child: child, ); } }
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.