【Flutter 实战】简约而不简单的计算器

【Flutter 实战】简约而不简单的计算器,第1张

概述老孟导读:这是 【Flutter 实战】组件系列文章的最后一篇,其他组件地址:http://laomengit.com/guide/widgets/Text.html,接下来将会讲解动画系列,关注老孟

老孟导读:这是 【Flutter 实战】组件系列文章的最后一篇,其他组件地址:http://laomengit.com/guide/widgets/Text.html,接下来将会讲解动画系列,关注老孟,精彩不断。

先看一下效果:

大家学习UI编程语言时喜欢用哪个 App 当作第一个练手的项目呢?,我喜欢使用 计算器 ,可能是习惯了吧,学习 AndroID 和 React Native 都用此 App 当作练手的项目。

下面我会一步一步的教大家如何实现此项目。

整个项目的 UI 分为两大部分,一部分是顶部显示数字和计算结果,另一部分是底部的输入按钮。

所以整体布局使用 Column,在不同分辨率的手机上,规定底部固定大小,剩余空间都由顶部组件填充,所以顶部组件使用 Expanded 扩充,代码如下:

Container(  padding: EdgeInsets.symmetric(horizontal: 18),child: Column(    children: <Widget>[      Expanded(        child: Container(          alignment: Alignment.bottomright,padding: EdgeInsets.only(right: 10),child: Text(            '$_text',maxlines: 1,style: TextStyle(                color: colors.white,FontSize: 48,FontWeight: FontWeight.w400),),SizedBox(        height: 20,_CalculatorKeyboard(        onValueChange: _onValueChange,SizedBox(        height: 80,)    ],)

SizedBox 组件用于两个组件之间的间隔。

_CalculatorKeyboard 是底部的输入按钮组件,也是此项目的重点,除了 0 这个按钮外,其余都是圆形按钮,不同之处是 高亮颜色(按住时颜色)、背景颜色、按钮文本、文本颜色不同,因此先实现一个按钮组件,代码如下:

Ink(  decoration: Boxdecoration(      color: color(0xFF363636),borderRadius: borderRadius.all(Radius.circular(200))),child: InkWell(    borderRadius: borderRadius.all(Radius.circular(200)),highlightcolor: color(0xFF363636),child: Container(      wIDth: 70,height: 70,alignment: Alignment.center,child: Text(        '1',style: TextStyle(color: colors.white,FontSize: 24),)

而 0 这个按钮的宽度是两个按钮的宽度 + 两个按钮的间隙,所以 0 按钮代码如下:

Ink(  decoration: Boxdecoration(      color: color(0xFF363636),child: Container(      wIDth: 158,child: Text(        '0',)

将按钮组件进行封装,其中高亮颜色(按住时颜色)、背景颜色、按钮文本、文本颜色属性作为参数,封装如下:

class _CalculatorItem extends StatelessWidget {  final String text;  final color textcolor;  final color color;  final color highlightcolor;  final double wIDth;  final ValueChanged<String> onValueChange;  _CalculatorItem(      {this.text,this.textcolor,this.color,this.highlightcolor,this.wIDth,this.onValueChange});  @overrIDe  Widget build(BuildContext context) {    return Ink(      decoration: Boxdecoration(          color: color,child: InkWell(        onTap: () {          onValueChange('$text');        },borderRadius: borderRadius.all(Radius.circular(200)),highlightcolor: highlightcolor ?? color,child: Container(          wIDth: wIDth ?? 70,padding: EdgeInsets.only(left: wIDth == null ? 0 : 25),alignment: wIDth == null ? Alignment.center : Alignment.centerleft,child: Text(            '$text',style: TextStyle(color: textcolor ?? colors.white,);  }}
输入按钮

输入按钮的布局使用 Wrap 布局组件,如果没有 0 这个组件也可以使用 GrIDVIEw组件,按钮的数据:

final List<Map> _keyboardList = [  {    'text': 'AC','textcolor': colors.black,'color': color(0xFFA5A5A5),'highlightcolor': color(0xFFD8D8D8)  },{    'text': '+/-',{    'text': '%',{    'text': '÷','color': color(0xFFE89E28),'highlightcolor': color(0xFFEDC68F)  },{'text': '7','color': color(0xFF363636)},{'text': '8',{'text': '9',{    'text': 'x',{'text': '4',{'text': '5',{'text': '6',{    'text': '-',{'text': '1',{'text': '2',{'text': '3',{    'text': '+',{'text': '0','color': color(0xFF363636),'wIDth': 158.0},{'text': '.',{    'text': '=',];

整个输入按钮组件:

class _CalculatorKeyboard extends StatelessWidget {  final ValueChanged<String> onValueChange;  const _CalculatorKeyboard({Key key,this.onValueChange}) : super(key: key);  @overrIDe  Widget build(BuildContext context) {    return Wrap(      runSpacing: 18,spacing: 18,children: List.generate(_keyboardList.length,(index) {        return _CalculatorItem(          text: _keyboardList[index]['text'],textcolor: _keyboardList[index]['textcolor'],color: _keyboardList[index]['color'],highlightcolor: _keyboardList[index]['highlightcolor'],wIDth: _keyboardList[index]['wIDth'],onValueChange: onValueChange,);      }),);  }}

onValueChange 是点击按钮的回调,参数是当前按钮的文本,用于计算,下面说下计算逻辑:

这里有4个变量:

_text:显示当前输入的数字和计算结果。_beforeText:用于保存被加数,比如输入 5+1,保存 5 ,用于后面的计算。_isResult:表示当前值是否为计算的结果,true:新输入数字直接显示,false:新输入数字和当前字符串相加,比如当前显示 5,如果是计算的结果,点击 1 时,直接显示1,否则显示 51。_operateText:保存加减乘除。

AC 按钮表示清空当前输入,显示 0,同时初始化其他变量:

case 'AC':  _text = '0';  _beforeText = '0';  _isResult = false;  break;

+/- 按钮表示对当前数字取反,比如 5->-5:

case '+/-':  if (_text.startsWith('-')) {    _text = _text.substring(1);  } else {    _text = '-$_text';  }  break;

% 按钮表示当前数除以100:

case '%':  double d = _value2Double(_text);  _isResult = true;  _text = '${d / 100.0}';  break;

+、-、x、÷ 按钮,保存当前 *** 作符号:

case '+':case '-':case 'x':case '÷':  _isResult = false;  _operateText = value;

0-9 和 . 按钮根据是否是计算结果和是否有 *** 作符号进行显示:

case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case '.':  if (_isResult) {    _text = value;  }  if (_operateText.isNotEmpty && _beforeText.isEmpty) {    _beforeText = _text;    _text = '';  }  _text += value;  if (_text.startsWith('0')) {    _text = _text.substring(1);  }  break;

= 按钮计算结果:

case '=':  double d = _value2Double(_beforeText);  double d1 = _value2Double(_text);  switch (_operateText) {    case '+':      _text = '${d + d1}';      break;    case '-':      _text = '${d - d1}';      break;    case 'x':      _text = '${d * d1}';      break;    case '÷':      _text = '${d / d1}';      break;  }  _beforeText = '';  _isResult = true;  _operateText = '';  break;double _value2Double(String value) {    if (_text.startsWith('-')) {      String s = value.substring(1);      return double.parse(s) * -1;    } else {      return double.parse(value);    }  }

回过头来,发现代码仅仅只有250多行,当然App也是有不足的地方:

不足之一:计算结果逻辑,上面计算结果的逻辑是不完美的,当增加一个 *** 作符(比如 取余),计算逻辑复杂度将会以指数级方式增加,那为什么还要用此方式?最重要的原因是计算结果逻辑不是此项目的重点,作为一个Flutter的入门项目重点是熟悉组件的使用,计算器的计算逻辑有一个比较著名的方式:后缀表达式的计算过程,然而此方式偏向于算法,对初学者非常不友好,因此,我采用了一种不完美但适合初学者的逻辑。不足之二:此App没有考虑横屏的情况,为什么?因为横屏很可能导致整体布局发生变化,横屏时按钮是变大还是拉伸,或者拉伸间隙?不同的方式使用的布局会发生变化,因此,目前只考虑了竖屏的布局,实际项目中要考虑横屏情况吗?其实这是一个用户体验的问题,首先问问自己,为什么要横屏?横屏可以显著的提升用户体验吗?如果不能,为什么要花费大力气适配横屏呢?交流

老孟Flutter博客地址(330个控件用法):http://laomengit.com

欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:

@H_419_207@

总结

以上是内存溢出为你收集整理的【Flutter 实战】简约而不简单的计算器全部内容,希望文章能够帮你解决【Flutter 实战】简约而不简单的计算器所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1000395.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存