当前位置:主页 > android教程 > Flutter投票组件

Flutter投票组件使用方法详解

发布:2023-03-02 16:00:01 59


本站精选了一篇相关的编程文章,网友充博文根据主题投稿了本篇教程内容,涉及到Flutter、投票组件、Flutter投票组件相关内容,已被772网友关注,下面的电子资料对本篇知识点有更加详尽的解释。

Flutter投票组件

本文实例为大家分享了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 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
    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 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: ''));
  }

  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中使用流式布局示例详解

    发布:2023-03-12

    这篇文章主要为大家介绍了flutter中使用流式布局示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


  • Android开发Flutter 桌面应用窗口化实战示例

    发布:2023-03-13

    这篇文章主要为大家介绍了Android开发Flutter 桌面应用窗口化实战示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


  • Flutter实现矩形取色器的封装

    发布:2023-03-02

    这篇文章主要为大家详细介绍了Flutter实现矩形取色器的封装,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下


  • Android Flutter实现精灵图的使用详解

    发布:2023-03-03

    在游戏开发中,精灵图会将一个人物所有动作放置在一张图片中,通过坐标定位选取其中一张图展示。本文就来教你如何使用精灵图,感兴趣的可以了解一下


  • Flutter学习LogUtil封装与实现实例详解

    发布:2023-03-06

    这篇文章主要为大家介绍了Flutter学习LogUtil封装与实现实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


  • UI 开源组件Flutter图表范围选择器使用详解

    发布:2023-03-04

    这篇文章主要为大家介绍了UI 开源组件Flutter图表范围选择器使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


  • Flutter有无状态类与State及生命周期详细介绍

    发布:2023-03-13

    这篇文章主要介绍了Flutter无状态类、有状态类、State、生命周期,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧


  • 详解flutter中常用的container layout实例

    发布:2023-03-07

    这篇文章主要为大家介绍了详解flutter中常用的container layout实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


网友讨论