热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

flutter实现数字刻度尺

flutter实现数字刻度尺-前言flutter实现一个刻度尺,和大家一起学习探讨。先上效果图:概述这个demo主要用到了flutter的自定义组件,无论是vue,an

前言
flutter实现一个刻度尺,和大家一起学习探讨。

先上效果图:

概述
这个demo主要用到了flutter的自定义组件,无论是vue,android亦或者是flutter,
前端自定义组件的思路大致都相同。
都是从
1.封装原有组件
2.组合原有组件暴露方法接口  
3.利用绘制实现自定义高的组件(Flutter中的绘制也是依靠Canvas和Paint来实现的)

在Flutter中使用自绘方式自定义Widget,大致需要以下步骤:继承CustomPainter并重写paint方法和shouldRepaint方法,在写paint方法中绘制内容,使用CustomPaint来构建Widget

class MyPainter extends CustomPainter {
  final int subGridWidth;

  final String valueStr;


  //0:列表首item 1:中间item 2:尾item
  final int type;

  final Color colorType;

  Paint _linePaint;

  double _lineWidth = 2;

  MyPainter(this.subGridWidth, this.valueStr, this.type,
      this.colorType) {
    _linePaint = Paint()
      ..isAntiAlias = true
      ..style = PaintingStyle.stroke
      ..strokeWidth = _lineWidth
      ..color = colorType;
  }

  @override
  void paint(Canvas canvas, Size size) {
    drawLine(canvas, size);
    drawText(canvas, size);
  }

  void drawLine(Canvas canvas, Size size) {
    double startY, endY;
    switch (type) {
      case 0: //首元素只绘制上半部分
        startY = size.height / 2;
        endY = size.height;
        break;
      case 2: //尾元素只绘制下半部分
        startY = 0;
        endY = size.height / 2;
        break;
      default: //中间元素全部绘制
        startY = 0;
        endY = size.height;
    }

    //绘制竖线
    for (double y = startY; y <= endY; y += subGridWidth) {
      if (y == size.height / 2) {
        //中间为长刻度
        canvas.drawLine(Offset(size.width - 100, y),
            Offset(size.width - 100 + size.height * 3 / 5, y), _linePaint);
      } else {
        //其他为短刻度
        canvas.drawLine(Offset(size.width - 100, y),
            Offset(size.width - 100 + size.height / 3, y), _linePaint);
      }
    }
  }

  void drawText(Canvas canvas, Size size) {
    //文字水平方向居中对齐,竖直方向底对齐
    ui.Paragraph p = _buildText(valueStr, size.width);
    //获得文字的宽高
    double halfWidth = p.minIntrinsicWidth / 2;
    double halfHeight = p.height / 2;
    canvas.drawParagraph(
        p, Offset(size.width - 160, size.height / 2 - halfHeight));
  }

  ui.Paragraph _buildText(String content, double maxWidth) {
    ui.ParagraphBuilder paragraphBuilder =
        ui.ParagraphBuilder(ui.ParagraphStyle());
    paragraphBuilder.pushStyle(
      ui.TextStyle(
        fontSize: 14,
        color: colorType,
        //fontFamily: "Montserrat",
      ),
    );
    paragraphBuilder.addText(content);

    ui.Paragraph paragraph = paragraphBuilder.build();
    paragraph.layout(ui.ParagraphConstraints(width: maxWidth));

    return paragraph;
  }


  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

其中

    _linePaint = Paint()
      //是否启动抗锯齿
      ..isAntiAlias = true
      //绘画风格,默认为填充,有fill和stroke两种
      ..style = PaintingStyle.stroke
      //画笔宽度
      ..strokeWidth = _lineWidth
      // 画笔颜色
      ..color = colorType;

通过创建一个段落构建器ui.ParagraphBuilder绘制字符串部分

    //字体样式
    paragraphBuilder.pushStyle(
      ui.TextStyle(
        fontSize: 14,
        color: colorType,
        //fontFamily: "Montserrat",
      ),
    );
    paragraphBuilder.addText(content);

    ui.Paragraph paragraph = paragraphBuilder.build();
    //限制绘制字符串宽度
    paragraph.layout(ui.ParagraphConstraints(width: maxWidth));

标尺一共有十个刻度,但是绘制的时候绘制11个刻度。第一个和最后一个只绘制一半的刻度。其他的全部绘制。目的将刻度尺的数值点(如:10分)对应的长刻度放在item的中间,便于绘制。

    switch (type) {
      case 0: //首元素只绘制上半部分
        startY = size.height / 2;
        endY = size.height;
        break;
      case 2: //尾元素只绘制下半部分
        startY = 0;
        endY = size.height / 2;
        break;
      default: //中间元素全部绘制
        startY = 0;
        endY = size.height;
    }

利用ListView绘制11个自定义组件打到10个刻度单位的标尺。

          ListView.builder(
            physics: ClampingScrollPhysics(),
            padding: EdgeInsets.all(0),
            scrollDirection: Axis.vertical,
            itemCount: 11,
            itemBuilder: (BuildContext context, int index) {
              //首尾空白元素
              int type;
              Color colorType;
              //第一个普通元素
              if (index == 0) {
                type = 0;
                //最后一个普通元素
              } else if (index == 10) {
                type = 2;
                //中间普通元素
              } else {
                type = 1;
              }
              if (index <5) {
                colorType = Color(0xFF55D160);
              } else if (index > 6) {
                colorType = Color(0xFFFF2C2C);
              } else {
                colorType = Color(0xFFFFA82C);
              }

              return Container(
                child: NumberPickerItem(
                  subGridCount: 10,
                  subGridWidth: 5,
                  itemWidth: widget.width.toInt(),
                  valueStr: ((10 - index) * 10).toString() + '分',
                  type: type,
                  colorType: colorType,
                ),
              );
            },
          ),


欢迎大家和我一起学习分享flutter,项目会持续更新新的学习demo

此项目的github地址:项目地址

下面是我们的公众号:flutter编程笔记(code9871)

公众号 不定期分享自己的学习想法

饮水思源,本demo参考了HorizontalNumberPicker项目。


推荐阅读
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • 本文整理了Java中org.gwtbootstrap3.client.ui.Icon.addDomHandler()方法的一些代码示例,展示了Icon.ad ... [详细]
  • 今日份分享:Flutter自定义之旋转木马
    今日份分享:Flutter自定义之旋转木马-先上图,带你回到童年时光:效果分析子布局按照圆形顺序放置且平分角度子布局旋转、支持手势滑动旋转、快速滑动抬手继续旋转、自动旋转支持X轴旋 ... [详细]
  • SmartRefreshLayout自定义头部刷新和底部加载
    1.添加依赖implementation‘com.scwang.smartrefresh:SmartRefreshLayout:1.0.3’implementation‘com.s ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 本文介绍了MVP架构模式及其在国庆技术博客中的应用。MVP架构模式是一种演变自MVC架构的新模式,其中View和Model之间的通信通过Presenter进行。相比MVC架构,MVP架构将交互逻辑放在Presenter内部,而View直接从Model中读取数据而不是通过Controller。本文还探讨了MVP架构在国庆技术博客中的具体应用。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • 带添加按钮的GridView,item的删除事件
    先上图片效果;gridView无数据时显示添加按钮,有数据时,第一格显示添加按钮,后面显示数据:布局文件:addr_manage.xml<?xmlve ... [详细]
  • 今天就跟大家聊聊有关怎么在Android应用中实现一个换肤功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根 ... [详细]
  • python3 logging
    python3logginghttps:docs.python.org3.5librarylogging.html,先3.5是因为我当前的python版本是3.5之所 ... [详细]
  • 在一对一直播源码使用过程中,有时会出现软键盘切换闪屏问题,就是当切换表情的时候屏幕会跳动,因此要对一对一直播源码表情面板无缝切换进行优化。 ... [详细]
author-avatar
501917112_0de975_837
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有