flutter 使用问题

作者: 问题饿 | 来源:发表于2022-06-20 17:33 被阅读0次
    1.在使用Textfield中遇到的问题

    flutter中的onchange方法和oc中的textField:(UITextField *)textField shouldChangeCharactersInRange:方法的不同
    onchange方法中调用刷新方法的时候,会导致循环进入方法中,光标乱闪

    ///对当前的TextField下的controller监听去刷视图
    _controller.addListener(() {
          setState(() {});
        });
    
    
    TextField(
                        controller: _controller,
                        focusNode: _focusNode,
                        textInputAction: TextInputAction.search,
                        style: TextStyle(fontSize: 17, color: Colours.text),
                        maxLines: 1,
                        cursorColor: Colours.app_main,
                        textCapitalization: TextCapitalization.characters,
                        inputFormatters: [
                          LengthLimitingTextInputFormatter(21),
                          FilteringTextInputFormatter.allow(RegExp('[a-z0-9A-Z ]')),
                        ],
                        decoration: InputDecoration(
                            border: InputBorder.none,
                            hintText: '请输入VIN码或点击图片上传',
                          ///这个右侧一键清除的按钮,不随着文字是否存在变动
                            suffixIcon: _controller.text.isNotEmpty
                                ? IconButton(
                                    icon: Icon(IconFont.guanbi,
                                        size: 15, color: Color(0x66000000)),
                                    onPressed: () => _controller.clear())
                                : null),
                        onChanged: (value) {
                          ///这边onchangge的方法,和oc中的输入监听不同,oc中的监听是实时监听,输入前,这个是后
                          var formateValue = _viewModel.getFormateVinCode(value);
    
                          if (formateValue.length % 4 == 0) {
                            var _newtext = _controller.text + ' ';
    
                            _controller.value = TextEditingValue(
                                text: _newtext,
                                selection: TextSelection.fromPosition(TextPosition(
                                    affinity: TextAffinity.downstream,
                                    offset: _newtext.length)));
                          }
                        },
                        onSubmitted: (value) {
                          do some thing...
                        },
                      ),
    
    2.wrap空间包含row问题

    Warp流控件中child中包含row控件的时候,要使用MainAxisSize.min的
    wrap流式布局的时候,里面使用了row进行自适应的时候,要采用上述的属性,不然wrap中每行都会充满,
    官方注释:

      /// Minimize the amount of free space along the main axis, subject to the
      /// incoming layout constraints.
      ///
      /// If the incoming layout constraints have a large enough
      /// [BoxConstraints.minWidth] or [BoxConstraints.minHeight], there might still
      /// be a non-zero amount of free space.
      ///
      /// If the incoming layout constraints are unbounded, and any children have a
      /// non-zero [FlexParentData.flex] and a [FlexFit.tight] fit (as applied by
      /// [Expanded]), the [RenderFlex] will assert, because there would be infinite
      /// remaining free space and boxes cannot be given infinite size.
    //最小化沿主轴的空闲空间,取决于
    //输入布局约束。
    ///如果传入的布局约束有足够大
    / / / [BoxConstraints。minWidth]或[BoxConstraints。可能还会有
    ///是一个非零的空闲空间。
    ///如果传入的布局约束是无界的,并且任何子元素都有
    / / /非零(FlexParentData。和一个[FlexFit. flex]。配合(如应用于
    /// [Expanded]), [RenderFlex]将断言,因为会有无限
    ///剩余的空闲空间和盒子不能被赋予无限的大小。
    

    wrap中每个只有在边界的时候有个强力约束,每个item没有强约束,所以导致在wrap中使用row控件的时候,row控件会沾满整个wrap控件的一行,充满了item的导致,设置min使其最小化空间约束,根据自控件的内容来进行最小布局约束。

    3.Flutter 标签字体下沉Bug
      @override
      Widget build(BuildContext context) {
        return Container(
          padding: EdgeInsets.symmetric(horizontal: 3,vertical: 1),
          decoration: BoxDecoration(
              color: widget.tagBackGroundColor,
              borderRadius: BorderRadius.circular(3)),
          child: Text(
            widget.tagString,
            textAlign: TextAlign.center,
            style: TextStyle(color: widget.tagTextColor, fontSize: 10),
          ),
        );
      }
    

    测试阶段发现,标签在不同的机器上,标签的样式都不一样。如果什么都不设置就会导致字体偏下。基于之前的React开发经验,基本可以确定是字体行高导致的问题。但是Flutter Text组件没有直接设置行高的地方,这就比较蛋疼,后来询问牛梦林,之前超人那边遇到过这种问题,只需Text设置strutStyle,指定fontSize和外层style设置的字体一致、设置合适的height即可,height值为14/10的值。

          child: Text(
            widget.tagString,
            textAlign: TextAlign.center,
            strutStyle: StrutStyle(fontSize: 10,height: 1.4),
            style: TextStyle(color: widget.tagTextColor, fontSize: 10),
          ),
    

    为什么height设置为1.4,因为默认fontSize为14,标签使用字体值为10,height默认放大1.4倍。

      /// The size of text (in logical pixels) to use when obtaining metrics from the font.
      ///
      /// The [fontSize] is used to get the base set of metrics that are then used to calculated
      /// the metrics of strut. The height and leading are expressed as a multiple of
      /// [fontSize].
      ///
      /// The default fontSize is 14 logical pixels.
      final double? fontSize;
    
    4.Flutter鸿蒙字体被截问题

    视觉反馈这个页面的时间字体被截,但是我的机器上都是好的,测试机器也是好的,然后我让视觉把测试机拿过来现场调试,发现是鸿蒙系统。后来慢慢排查,找到了解决方案,只需给包裹Text的外层容器设置一层白色背景即可。

    5.Flutter长数字字母省略的显示问题

    期望展示效果,单号位置,超出宽度末尾...省略展示
    通常做法对Text设置overflow:

    overflow: TextOverflow.ellipsis
    

    但以上属性的缺陷是,当遇到长数字,长字母时,会被整体省略:
    利用零宽空格字符处理这个问题:

    ///插入零宽空格字符
      String breakWord(String word) {
        if (word == null || word.isEmpty) {
          return word;
        }
        var breakWord = ' ';
        word.runes.forEach((element) {
          breakWord += String.fromCharCode(element);
          breakWord += '\u200B';
        });
        return breakWord;
      }
    
    
    text: breakWord(value),
    

    另一种写法

    text: value.replaceAll('', '\u200B')
    

    两种写法,在实际展示样式上,视觉显示宽度略有差异。
    此外,第二种写法,用replaceAll在处理包含emoji的字符串时会出现not utf-16的问题。

    看情况使用以上两种方式处理即可。

    6.Flutter中设置图片宽高失效问题

    如下代码,发现设置图片宽高无效

    Container(
      width: 30,
      height: 30,
      decoration: BoxDecoration(
        color: ThemeColors.halfTranslucent,
        borderRadius: BorderRadius.circular(15)),
      child: LoadAssetImage("ic_back",width: 24,height: 24,)
    )
    

    解决方案:在LoadAssetImage前再包一层即可生效

    Container(
      width: 30,
      height: 30,
      decoration: BoxDecoration(
        color: ThemeColors.halfTranslucent,
        borderRadius: BorderRadius.circular(15)),
      child: Center(
        child: LoadAssetImage("ic_back",width: 24,height: 24,),
      ),
    )
    
    7.Flutter中double精度问题

    背景:由于 Dart 使用了和js一样的 IEEE 754 双精度标准进行存储,所以存在和JS一样的精度计算问题

    解决方案:采用decimal这个三方库解决
      #解决精度问题
      decimal: 0.3.5
    refundAmount =
      "${Decimal.parse("$amountDesc") * Decimal.parse("$refundNumber")}";
    
    8.键盘遮挡问题

    1.存在在输入文字的时候,若不选择选择文字预览文字情况下,直接点击拍照,会导致在拍照界面出现键盘,无法进行收起

    2.移动开单2.0侧筛界面,当选择确认按钮的时候,一直点击,会导致pop页面多次的情况,导致界面进行多次返回的情况。

    原因:

    1.该情况,在做收起键盘的操作的时候,未点击预览文字时,直接跳转下个界面的时候,会导致键盘没有完全收起来,同时下面收起键盘的方法的时候,虽然收起了键盘,但是光标仍然存在。

    SystemChannels.textInput.invokeMethod('TextInput.hide');
    

    2.侧边页面出现的时候,一直点击确定按钮的时候,会调多次pop方法,会导致关闭抽屉栏页面后,页面还会存在调用一个pop的问题,导致会产生返回上一个界面的问题。

    解决

    1.使用该方法,收起键盘的同时收起光标,在空白,滑动,点击弹框的时候均收起键盘

    FocusScope.of(context).requestFocus(FocusNode());
    

    2.在点击确定的时候,增加标志位,在页面销毁之前,只会调用一次。


    1655715619775.jpg

    防抖解决方法:

    新增到公共库里,支持自定义防抖时间,默认一秒防抖

    import 'dart:async';
    
    ///按钮防抖,milliseconds防抖时间,默认1秒
    Function debounce(Function func, {int milliseconds = 1000}) {
      Timer timer;
      Function target = () {
        if (timer?.isActive ?? false) {
          timer?.cancel();
        }
        timer = Timer(Duration(milliseconds: milliseconds), () {
          func?.call();
        });
      };
      return target;
    }
    

    使用

    child: GestureDetector(
           onTap: debounce(() {
           print('点击了');
        },milliseconds:1500),
      ),
    
    9.flutter时间格式转换问题

    //正常情况下时间格式转字符
    var selectedTimeStr =
    selectedMonth ?? DateFormat('yyyy-MM').format(DateTime.now());
    //可以将时间戳转成对应的字符串

    var selectedMonth = '2022-06',

    //将字符串转时间戳的时候,正常使用parse方法
    var parseTime = DateTime.parse(selectedMonth);

    //但是parse只能针对标准格式转化的,比如2022-06这个就无法转,只能转下面标准格式,
    //否则会报FormatException错
    /// * "2012-02-27"
    /// * "2012-02-27 13:27:00"
    /// * "2012-02-27 13:27:00.123456789z"
    /// * "2012-02-27 13:27:00,123456789z"
    /// * "20120227 13:27:00"
    /// * "20120227T132700"
    /// * "20120227"
    /// * "+20120227"
    /// * "2012-02-27T14Z"
    /// * "2012-02-27T14+00:00"
    /// * "-123450101 00:00:00 Z": in the year -12345.
    /// * "2002-02-27T14:00:00-0500": Same as "2002-02-27T19:00:00Z"

    //使用下面可以解决报错问题,但是无法正确解析,返回的是now的时间格式
    var tryParseTime = DateTime.tryParse(selectedMonth) ?? DateTime.now();

    //使用下面的可以正常解析
    var parseStrictTime = DateFormat('yyyy-MM').parseStrict(selectedMonth);

    //parseStrict可以解析任意格式保持统一的,下面的可以解析成2022-01-01 0000000时间

    selectedMonth = '2022-';
    parseStrictTime =  DateFormat('yyyy-').parseStrict(selectedMonth);
    

    相关文章

      网友评论

        本文标题:flutter 使用问题

        本文链接:https://www.haomeiwen.com/subject/uujjvrtx.html