flutter 开发中的问题与技巧

一、概述

        刚开始上手 flutter 开发的时候,总会遇到这样那样的小问题,而官方文档又没有明确说明不能这样使用,本文总结了一些开发中经常会遇到的一些问题和一些开发小技巧。

二、常见问题


1、Expanded 组件只能在 Row、Column、Flex 中使用

Container(color: Colors.green,child: const Expanded(child: Text('出错了!'),),
)

以上使用将会报错,在 debug 模式下可以显示出来,但控制台会抛出异常,release 模式直接不显示,报错信息如下:

======== Exception caught by widgets library =======================================================
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type FlexParentData to a RenderObject, which has been set up to accept ParentData of incompatible type ParentData.Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. Typically, Expanded widgets are placed directly inside Flex widgets.
The offending Expanded is currently placed inside a ColoredBox widget.


2、Container 组件中 color 和 decoration 不能同时设置

Container(color: Colors.red,decoration: const BoxDecoration(color: Color(0xFFCE9F76),borderRadius: BorderRadius.all(Radius.circular(10)),),child: const Text('文本展示'),
)

上述用法将会报错,页面爆红展示错误信息:

======== Exception caught by widgets library =======================================================
The following assertion was thrown building HomePage(dirty, state: _HomePageState#57a29):
Cannot provide both a color and a decoration
To provide both, use "decoration: BoxDecoration(color: color)".
'package:flutter/src/widgets/container.dart':
Failed assertion: line 273 pos 15: 'color == null || decoration == null'

3、Column、Row 等没有固定宽高的组件在嵌套 ListView、GridView 等可扩展宽高的组件会有异常抛出:

Column(children: [ListView.separated(itemBuilder: (context, index) {return ListTile(title: Text('第$index项'),);},separatorBuilder: (context, index) {return const Divider(color: Colors.orange,);},itemCount: 20)],)

上述问题会抛出如下异常:

======== Exception caught by rendering library =====================================================
The following assertion was thrown during performResize():
Vertical viewport was given unbounded height.Viewports expand in the scrolling direction to fill their container. In this case, a vertical viewport was given an unlimited amount of vertical space in which to expand. This situation typically happens when a scrollable widget is nested inside another scrollable widget.If this widget is always nested in a scrollable widget there is no need to use a viewport because there will always be enough vertical space for the children. In this case, consider using a Column or Wrap instead. Otherwise, consider using a CustomScrollView to concatenate arbitrary slivers into a single scrollable.

错误说明很明显,垂直视口的高度没有边界,此时可以通过给 ListView 外面套一个具有固定高度的盒子比如 SizeBox 或者嵌套一个可扩展高度的组件 Expanded 解决

// 固定视口高度,此时无法准确填充屏幕剩余空间
Column(children: [SizedBox(height: 500,child: ListView.separated(itemBuilder: (context, index) {return ListTile(title: Text('第$index项'),);},separatorBuilder: (context, index) {return const Divider(color: Colors.orange,);},itemCount: 20),)],
)// 使用 Expanded 可以准确填充屏幕剩余空间
Column(children: [Expanded(child: ListView.separated(itemBuilder: (context, index) {return ListTile(title: Text('第$index项'),);},separatorBuilder: (context, index) {return const Divider(color: Colors.orange,);},itemCount: 20),)],
)

当列表项不是很多,或者存在列表嵌套,还可以通过下面的方式解决:

// 配置 ListView 的 shrinkWrap 属性
shrinkWrap: true,


注意:

  • 如果列表项过多,超过屏幕剩余可展示空间,屏幕会溢出
  • 这种方式只适用列表项不多的情况,性能不太好,会一次性渲染所有子 item
  • 当只需要外层滚动,内层列表不滚动时可以配置这个属性 physics: NeverScrollableScrollPhysics()

4、圆角矩形 border 被裁剪

Container(clipBehavior: Clip.hardEdge,decoration: BoxDecoration(borderRadius: BorderRadius.circular(10),border:Border.all(color: Colors.red, width: 2),),// position: DecorationPosition.foreground,child: Image.network('https://desk-fd.zol-img.com.cn/t_s960x600c5/g6/M00/03/0E/ChMkKWDZLXSICljFAC1U9uUHfekAARQfgG_oL0ALVUO515.jpg',fit: BoxFit.cover,width: 100,height: 100,errorBuilder: (context, error, stackTrace) => Image.asset('assets/images/4.0x/home/ic_round_rect_grey_60.png',width: 100,height: 100,)),
)

上述圆角裁剪方式同时存在圆角与边框,会存在边框显示不全被裁剪的情况 

Screenshot_20221129_152416.png


此时可以对图片单独进行一次裁剪即可解决问题,或者更换其他圆角裁剪方式来替换 decoration


5、TextField 长按出现复制粘贴的英文提示:

Screenshot_20221129_165224.png

有 3 种解决方式:

1、可以通过给TextField设置如下属性来禁用这一提示,此时无法选中任何输入内容:

enableInteractiveSelection: false,

2、可以通过给TextField设置如下属性来禁用这一提示,此时可以选中输入内容但是不会有提示窗口:

toolbarOptions: ToolbarOptions()

3、如果要继续保留以上提示,可使用 flutter 提供的国际化来修改为中文显示:

// 配置依赖
dependencies:flutter:sdk: flutterflutter_localizations:sdk: flutter// 增加国际化处理
return MaterialApp(localizationsDelegates: [GlobalMaterialLocalizations.delegate,GlobalWidgetsLocalizations.delegate,GlobalCupertinoLocalizations.delegate, //iOS],supportedLocales: [const Locale('zh', 'CN'),const Locale('en', 'US'),]
}

三、开发技巧


1、键盘弹出后导致页面溢出

Screenshot_20221128_180138.png

通常可以通过在根布局中嵌套一层 SingleChildScrollView 来解决


2、键盘弹起会自动将页面顶上去,以保证键盘刚好在输入框下方(dialog 中不适用),有时候不需要顶起页面,可以在页面的 Scaffold 中如下配置禁止页面被顶起

resizeToAvoidBottomInset: false

Screenshot_20221128_190444.pngScreenshot_20221128_185026.png


3、使用GestureDetector的透明部分点击无效,导致点击范围很小,可以在 GestureDetector 里面加以下代码,提高点击的灵敏度:

behavior: HitTestBehavior.opaque


4、在部分机型上,页面底部与系统 home 导航条重叠了,尤其是在 iphone 系统上,出现此适配问题,以及 Android手机布局浸入到状态栏的问题,此时可以将页面根组件使用以下组件包裹来解决:

SafeArea(child: Colunm())


5、实现圆角的几种方式

  • 通过设置 Container 的 decoration 来实现:
Container(margin: const EdgeInsets.all(10),decoration: BoxDecoration(color: Colors.orange,borderRadius: BorderRadius.circular(8),),child: Column(children: List.generate(5, (index) {return ListTile(title: Text('第$index个'));}),))

Screenshot_20221129_140144.png

  • 通过 PhysicalModel 来实现:
Padding(padding: const EdgeInsets.all(10.0),child: PhysicalModel(borderRadius: BorderRadius.circular(10),color: Colors.green,clipBehavior: Clip.hardEdge,child: Column(children: List.generate(5,(index) => ListTile(title: Text('第$index个'),)),)),
)

Screenshot_20221129_141002.png

  • 通过 ClipRRect 实现
Padding(padding: const EdgeInsets.all(10.0),child: ClipRRect(borderRadius: BorderRadius.circular(10),child: Container(color: Colors.orange,child: Column(children: List.generate(5,(index) => ListTile(title: Text('第几=$index个'),)),),),),
)

Screenshot_20221129_141500.png


●使用 CircleAvatar 来实现:

Padding(padding: EdgeInsets.all(10),child: CircleAvatar(radius: 50,backgroundColor: Colors.white, //未设置背景色,加载图片时会显示红色backgroundImage: NetworkImage("https://desk-fd.zol-img.com.cn/t_s960x600c5/g6/M00/03/0E/ChMkKWDZLXSICljFAC1U9uUHfekAARQfgG_oL0ALVUO515.jpg")),
)

Screenshot_20221129_142505.png

  • 使用 ClipOval 实现,效果同上
Padding(padding: const EdgeInsets.all(10),child: ClipOval(child: Image.network("https://desk-fd.zol-img.com.cn/t_s960x600c5/g6/M00/03/0E/ChMkKWDZLXSICljFAC1U9uUHfekAARQfgG_oL0ALVUO515.jpg",width: 100,height: 100,fit: BoxFit.cover,),),
)

●使用 Container 配合 decoration 的 ShapeDecoration 可以实现多种不同的效果(只适用背景)

// 斜切角形状示例
Padding(padding: const EdgeInsets.all(10.0),child: Column(children: [//斜切角形状示例Container(width: 120,height: 120,decoration: ShapeDecoration(shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(16)),image: const DecorationImage(fit: BoxFit.cover,image: NetworkImage('https://pic2.zhimg.com/v2-639b49f2f6578eabddc458b84eb3c6a1.jpg'))))],),
)

使用ShapeDecoration可以做出各种形状:


斜切角: BeveledRectangleBorder

圆角矩形: RoundedRectangleBorder

超椭圆: SuperellipseShape

体育场: StadiumBorder

圆形: CircleBorder

image.png


6、想在添加或者删除列表项时添加对应的动画效果可以使用 AnimatedList 代替 ListView

AnimatedList(itemBuilder: (context,index){return ListTile(title: Text('第$index个'),)
})


7、添加Material触摸水波效果

InkWell(onTap: (){},child: Container(// color: Colors.orange,width: 100,height: 100,child: Text('点击水波效果')),
)

注意:

  • 如果子组件有设置颜色将会看不到水波效果
  • 必须设置点击事件监听,否则水波效果也不会触发

8、当引入的多个库有同名类冲突时,可以使用 as 制定别名解决:

import 'package:myproject/MyCustomClass.dart' as myclass;
// 使用的时候:
myclass.CustomClassType _myCustom;

9、控制组件可见性的几种方法:

  • 包裹 Visibility 组件(默认不占位):

Visibility(visible: true, child: Text('这里是一段文字'))// 有几个属性需要注意一下:
child     子组件
visible   子组件是否可见,默认true(可见)
replacement 不可见时显示的组件(当maintainState = false)
maintainAnimation 不可见时,是否维持子组件中的动画 
maintainSize 不可见时是否留有空间(设置为true) 
maintainSemantics  不可见时是否维持它的语义
maintainInteractivity 不可见时是否具有交互性 注意:maintainSize就是保持大小不变,如果只设置这个属性,会报错,另外两个属性:maintainAnimation和maintainState也必须同时设置
  • 包裹 Offstage 组件(不占位):
Offstage(offstage: true, // 子组件是否可见,默认true(隐藏)child: Container(color: Colors.green,height: 100,width: 100,child: Text('这里是一段文字')))当offstaged设置为true,子组件不可见,但仍处于activity状态。
如果不展示的时候有动画在执行,需要手动关闭动画
  • 包裹 Opacity 组件(占位,改变透明度):
Opacity(opacity: 0.1,child: Container(color: Colors.green,height: 100,width: 100,child: Text('这里是一段文字')))当设置透明度为0时,不展示,但在Widget Tree中存在。
如果不可见的时候需要占用大小,将alwaysIncludeSemantics设为true。

10、如果两个叠加的widget,上面的widget不需要处理点击事件,下面的需要处理,可以在上面的widget中包裹一层IgnorePointer

11、如果TextFiled需要输入带有ip地址的数字,需要小数点.,可以如下设置

keyboardType: TextInputType.numberWithOptions(decimal: true)

四、总结

目前遇到的比较常见的问题就这么多,后续遇到了新问题再补充,持续更新中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/104133.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

缓存设计的创新之旅:架构的灵魂之一

缓存在架构设计中占有重要地位。缓存在提升性能中也扮演重要的角色。常见的有对资源的缓存,比如数据库连接池、http连接池,还有对数据的缓存等。缓存的设计可复杂也可简单,但是需要考虑的点却很多。 缓存对象 设计缓存的时候一定要考虑的是&…

行业追踪,2023-10-13

自动复盘 2023-10-13 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…

3D 生成重建007-Fantasia3D和Magic3d两阶段玩转文生3D

3D生成重建3D 生成重建007-Fantasia3D和magic3d 文章目录 0 论文工作1 论文方法1.1 magic3d1.2 Fantasia3D 2 效果2.1 magic3d2.2 fantasia3d 0 论文工作 两篇论文都是两阶段法进行文生3d,其中fantasia3D主要对形状和外表进行解耦,然后先对geometry进行…

微服务11-Sentinel中的授权规则以及Sentinel服务规则持久化

文章目录 授权规则自定义异常结果规则持久化实现Push模式 授权规则 根据来源名称对请求进行拦截 ——>我们需要解析来源名称(RequestOriginParser默认解析都为default),所以我们要自定义一个实现类(根据请求头解析&#xff0c…

springcloud笔记(7)-限流降级Sentinel

官方文档:概述 | Spring Cloud Alibaba basic-api-resource-rule | Sentinel (sentinelguard.io) Sentinel是SpringCloudAlibaba的组件。 sentinel的功能 introduction | Sentinel 流量控制 熔断降级:降低调用链路中的不稳定资源 系统负载保护&am…

private key ssh连接服务器

这里用到的软件是PuTTY。 https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html 保存本地rsa文件后,打开软件PuTTYgen,点击Load导入文件,输入Key passphrase即密码,保存至本地。 随后在PuTTY配置ssh的用户名 来Cred…

纽带|MaaS,连接AI与商业落地,重塑行业版图

熟悉人工智能的你可曾听过“MaaS”?MaaS实际上便是模型即服务(Model as a Service)的英文首字母组合。 它代表着一种全新的AI应用思维方式,将AI模型封装成可调用的云服务,通过云平台呈现给广大用户,其核心…

Rocket Typist pro for mac 「Macos文本快速输入工具」

Rocket Typist Pro是一款在Mac上使用的文本快速输入工具,它可以帮助用户更快速、更准确地输入文本。 这款软件的设计非常简单、高效,它通过使用短语或宏,可以快速插入文本,减少重复性工作,提高工作效率。 Rocket Typ…

【大数据】Hadoop MapReduce与Hadoop YARN(学习笔记)

一、Hadoop MapReduce介绍 1、设计构思 1)如何对付大数据处理场景 对相互间不具有计算依赖关系的大数据计算任务,实现并行最自然的办法就是采取MapReduce分而治之的策略。 不可拆分的计算任务或相互间有依赖关系的数据无法进行并行计算! …

Spring实战 | Spring AOP核心功能分析之葵花宝典

国庆中秋特辑系列文章: 国庆中秋特辑(八)Spring Boot项目如何使用JPA 国庆中秋特辑(七)Java软件工程师常见20道编程面试题 国庆中秋特辑(六)大学生常见30道宝藏编程面试题 国庆中秋特辑&…

计算机毕业设计选什么题目好?springboot 试题库管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

学信息系统项目管理师第4版系列26_项目绩效域(下)

1. 项目工作绩效域 1.1. 涉及项目工作相关的活动和职能 1.2. 预期目标 1.2.1. 高效且有效的项目绩效 1.2.2. 适合项目和环境的项目过程 1.2.3. 干系人适当的沟通和参与 1.2.4. 对实物资源进行了有效管理 1.2.5. 对采购进行了有效管理 1.2.6. 有效处理了变更 1.2.7. 通…

互联网Java工程师面试题·Java 并发编程篇·第五弹

目录 52、什么是线程池? 为什么要使用它? 53、怎么检测一个线程是否拥有锁? 54、你如何在 Java 中获取线程堆栈? 55、JVM 中哪个参数是用来控制线程的栈堆栈小的? 56、Thread 类中的 yield 方法有什么作用? 57、…

C语言达到什么水平才能从事单片机工作

C语言达到什么水平才能从事单片机工作 从事单片机工作需要具备一定的C语言编程水平。以下是几个关键要点:基本C语言知识: 掌握C语言的基本语法、数据类型、运算符、流控制语句和函数等基本概念。最近很多小伙伴找我,说想要一些C语言学习资料&…

晨控CK-GW06系列网关与汇川可编程控制器MOSBUSTCP通讯手册

晨控CK-GW06系列网关与汇川可编程控制器MOSBUSTCP通讯手册 晨控CK-GW06系列是支持标准工业通讯协议 MODBUSTCP 的网关控制器,方便用户集成到PLC等控制系统中。本控制器提供了网络 POE 供电和直流电源供电两种方式,确保用户在使用无 POE 供电功能的交换机时可采用外…

用wpf替代winform 解决PLC数据量过大页面卡顿的问题

winform 由于不是数据驱动, 页面想刷新数据必须刷新控件, wpf则不用. 可以利用wpf 的数据绑定和IOC, 页面中的消息传递, itemscontrol 实现大量数据刷新, 上位机页面不卡顿 跨页面传值, 可以用两种方法: Toolkit.Mvvm中的Message和IOC. 下面是代码: using Microsoft.Extensio…

3.2.5:VBA对单元格操作的引申

我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的劳动效率,而且可以提高数据处理的准确度。我推出的VBA系列教程共九套和一部VBA汉英手册,现在已经全部完成,希望大家利用、学习。 如果…

解锁机器学习-梯度下降:从技术到实战的全面指南

目录 一、简介什么是梯度下降?为什么梯度下降重要? 二、梯度下降的数学原理代价函数(Cost Function)梯度(Gradient)更新规则代码示例:基础的梯度下降更新规则 三、批量梯度下降(Batc…

MySQL创建数据库、创建表操作和用户权限

1、创建数据库school,字符集为utf8 2、在school数据库中创建Student和Score表 3、授权用户tom,密码Mysql123,能够从任何地方登录并管理数据库school 4、使用mysql客户端登录服务器,重置root密码

JavaScript之正则表达式

详见MDN 正则表达式(RegExp) 正则表达式不是JS独有的内容,大部分语言都支持正则表达式 JS中正则表达式使用得不是那么多,我们可以尽量避免使用正则表达式 在JS中,正则表达式就是RegExp对象,RegExp 对象用于将文本与一个模式匹配 正…