Flutter投票组件使用方法详解

Ava ·
更新时间:2024-11-14
· 1865 次阅读

本文实例为大家分享了Flutter投票组件的使用方法,供大家参考,具体内容如下

前景

基于公司项目需求,仿照微博实现投票功能。

开发遇到的问题

1.选项列表的高度,自适应的问题;
2.进度条动画的问题;
3.列表回收机制,导致进度条动画重复;
4.自定义进度条四周圆角;

如何解决问题

拿到数组列表最长的数据,然后根据屏幕宽度计算,超出一行则设定两行高度,否则使用一行的高度;

_didExceedOneMoreLines(String text, double width, TextStyle style) {     final span = TextSpan(text: text, style: style);     final tp =         TextPainter(text: span, maxLines: 1, textDirection: TextDirection.ltr);     tp.layout(maxWidth: width);     if (tp.didExceedMaxLines) {     //设置item选项的高度       _itemHeight = 100.w;     }   }

Widget控件初始化(initState)方法时,使用AnimationController动画,并实现SingleTickerProviderStateMixin,在build方法当中调用 _controller.animateTo()

AnimationController _controller;     _controller = AnimationController(       vsync: this,       duration: const Duration(seconds: 1),     )..addListener(() {         setState(() {});       }); //触发动画,执行的位置 _controller.animateTo()

在列表数据当中给动画标记字段,让其是否执行动画;当用户投票成功,改变状态执行进度条动画。用户滑动列表之后,将标记改为false。关闭动画效果。

针对修改部分源码,设置进度条圆角控件;

import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; class RoundLinearProgressPainter extends ProgressIndicator {   const RoundLinearProgressPainter({     Key key,     double value,     Color backgroundColor,     Color color,     Animation<Color> valueColor,     this.minHeight,     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() {     super.initState();     _controller = AnimationController(       duration: const Duration(milliseconds: 1),       vsync: this,     )..addListener(() {         setState(() {});       });     if (widget.value != null) _controller.forward();   }   @override   Widget build(BuildContext context) {     return widget._buildSemanticsWrapper(       context: context,       child: Container(         constraints: BoxConstraints(           minWidth: double.infinity,           minHeight: widget.minHeight ?? 4.0,         ),         child: CustomPaint(           painter: _LinearProgressIndicatorPainter(             backgroundColor: widget._getBackgroundColor(context),             valueColor: widget._getValueColor(context),             value: widget.value,             animationValue: _controller.value,           ),         ),       ),     );   }   @override   void didUpdateWidget(RoundLinearProgressPainter oldWidget) {     super.didUpdateWidget(oldWidget);     if (widget.value == null && !_controller.isAnimating)       _controller.repeat();     else if (widget.value != null && _controller.isAnimating)       _controller.stop();   }   @override   void dispose() {     _controller.dispose();     super.dispose();   } } class _LinearProgressIndicatorPainter extends CustomPainter {   const _LinearProgressIndicatorPainter({     this.backgroundColor,     this.valueColor,     this.value,     this.animationValue,   });   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 = PaintingStyle.fill;     canvas.drawRect(Offset.zero & size, paint);     paint.color = valueColor;     void drawBar(double x, double width) {       if (width <= 0.0) return;       RRect rRect;       ///圆角的宽度       var radius = Radius.circular(8.w);       if (value == 1.0) {       ///当进度条为1时,设置四周圆角         rRect = RRect.fromRectAndRadius(             Offset(0.0, 0.0) & Size(width, size.height), radius);       } else {         ///小于1时,设置左侧圆角         rRect = RRect.fromRectAndCorners(             Offset(0.0, 0.0) & Size(width, size.height),             topLeft: radius,             bottomLeft: radius);       }       canvas.drawRRect(rRect, paint);     }     if (value != null) {       drawBar(0.0, value.clamp(0.0, 1.0) * size.width);     }   }   @override   bool shouldRepaint(_LinearProgressIndicatorPainter oldPainter) {     return oldPainter.backgroundColor != backgroundColor ||         oldPainter.valueColor != valueColor ||         oldPainter.value != value ||         oldPainter.animationValue != animationValue;   } } abstract class ProgressIndicator extends StatefulWidget {   const ProgressIndicator({     Key key,     this.value,     this.backgroundColor,     this.color,     this.valueColor,     this.semanticsLabel,     this.semanticsValue,   }) : 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 ?? Theme.of(context).colorScheme.background;   Color _getValueColor(BuildContext context) =>       valueColor?.value ?? color ?? Theme.of(context).colorScheme.primary;   @override   void debugFillProperties(DiagnosticPropertiesBuilder properties) {     super.debugFillProperties(properties);     properties.add(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,     );   } }



方法 flutter

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章