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.rhkb.cn/news/157490.html

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

相关文章

GEE:基于GLDAS数据集分析土壤湿度的时间序列变化

作者:CSDN @ _养乐多_ 本篇博客将介绍如何使用Google Earth Engine(GEE)进行土壤湿度数据的分析。我们将使用NASA GLDAS(Global Land Data Assimilation System)数据集,其中包括了关于土壤湿度的信息。通过该数据集,我们将了解土壤湿度在特定区域和时间段内的变化,并生…

springboot vue 部署至Rocky(Centos)并自启,本文部署是若依应用

概述 1、安装nohup(后台进程运行java) 2、安装中文字体(防止中文乱码) 3、安装chrony(保证分布式部署时间的一致性) 5、安装mysql数据,迁移目录,并授权自启动; 6、安…

SpringBoot注解篇之@Validated

目录 前言Validated作用NotNull与NotBlank区别总结 前言 大家好,我是AK,在做新项目顺便整理SpringBoot相关内容,这里主要介绍下Validated注解的应用,减少核心业务逻辑中一些参数判断的代码。 Validated作用 Validated 是 Spring…

Linux友人帐之系统管理与虚拟机相关

一、虚拟机相关操作 1.1虚拟机克隆 虚拟机克隆是指将一个已经安装好的虚拟机复制出一个或多个完全相同的副本,包括虚拟机的配置、操作系统、应用程序等,从而节省安装和配置的时间和资源。 虚拟机克隆的主要用途有: 创建多个相同或相似的虚拟…

论文导读|八月下旬Operations Research文章精选:定价问题专题

编者按: ​ ​在“ Operations Research论文精选”中,我们有主题、有针对性地选择了Operations Research中一些有趣的文章,不仅对文章的内容进行了概括与点评,而且也对文章的结构进行了梳理,旨在激发广大读者的阅读兴…

win10搭建gtest测试环境+vs2019

首先是下载gtest,这个我已经放在了博客上方资源绑定处,这个适用于win10vs版本,关于liunx版本的不能用这个。 或者百度网盘链接: 链接:https://pan.baidu.com/s/15m62KAJ29vNe1mrmAcmehA 提取码:vfxz 下…

asp.net会议预约管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net 会议预约管理系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使用c#语 言开发 asp.net 会议预约管理系统 二、…

miRNA测序数据生信分析——第四讲,未知物种的生信分析实例

miRNA测序数据生信分析——第四讲,未知物种的生信分析实例 miRNA测序数据生信分析——第四讲,未知物种的生信分析实例1. 下载测序数据2. 原始数据质控——软件fastqc3. 注释tRNA和rRNA,使用Rfam数据库——软件blast,Rfam_statisti…

Excel 插入和提取超链接

构造超链接 HYPERLINK(D1,C1)提取超链接 Sheet页→右键→查看代码Sub link()Dim hl As HyperlinkFor Each hl In ActiveSheet.Hyperlinkshl.Range.Offset(0, 1).Value hl.AddressNext End Sub工具栏→运行→运行子过程→提取所有超链接地址参考: https://blog.cs…

C++编程基础|多级指针

C编程基础|多级指针 一级指针二级指针三级指针多级指针的意义一维数组与数组指针二维数组与数组指针 在看代码时发现下面的内容 GridNodePtr *** GridNodeMap;struct GridNode; typedef GridNode* GridNodePtr;显而GridNodePtr是结构体GridNode首地址指针 那么GridNodeMap是什…

暴力递归转动态规划(九)

题目 题有点难,但还挺有趣 有一个咖啡机数组arr[],其中arr[i]代表每一个咖啡机冲泡咖啡所需的时间,有整数N,代表着准备冲咖啡的N个人(假设这个人拿到咖啡后喝完的时间为0,拿手里咖啡杯即变空)&a…

09_Webpack打包工具

1 初识Webpack 1.1 什么是Webpack Webpack打包工具对项目中的复杂文件进行打包处理,可以实现项目的自动化构建,并且给前端开发人员带来了极大的便利。 目前,企业中的绝大多数前端项目是基于Webpack打包工具来进行开发的。 1.2 Webpack的安…

CentOS 7系统安装配置Zabbix 5.0LTS 步骤

目录 一、查看Zabbix官方教程(重点) 二、安装 Docker 创建 Mysql 容器 安装 Docker 依赖包 添加 Docker 官方仓库 安装 Docker 引擎 启动 Docker 服务并设置开机自启 验证 Docker 是否成功安装 拉取 MySQL 镜像 查看本地镜像 运行容器 停止和启…

安装项目运行环境(python依赖包+allure)

目录 一、安装自动化项目依赖包1.导出项目依赖库2.上传到远程仓库3.进入jenkins容器内,检查是否安装git4.配置git用户信息5.生成秘钥6.把代码拉取下来7.安装python项目依赖8.运行项目 二、安装allure1.jenkins容器内安装allure,进入/usr/local/2.下载all…

IIS 解析漏洞复现

文章目录 IIS 解析漏洞复现1. 漏洞描述2. 漏洞复现3. 漏洞原因4. 安全加固5. 安全防护 IIS 解析漏洞复现 1. 漏洞描述 说明内容漏洞编号漏洞名称IIS 解析漏洞漏洞评级高危影响范围IIS 6.0及以前版本IIS 7.0IIS 7.5漏洞描述IIS 解析漏洞是指在 IIS 服务器上存在的安全漏洞&…

【Hello Algorithm】暴力递归到动态规划(一)

暴力递归到动态规划(一) 斐波那契数列的动态规划机器人走路初级递归初级动态规划动态规划 先后选牌问题初级递归初级动态规划动态规划 我们可以一句话总结下动态规划 动态规划本质是一种以空间换时间的行为 如果你发现有重复调用的过程 在经过一次之后把…

GRU的 电影评论情感分析 - python 深度学习 情感分类 计算机竞赛

1 前言 🔥学长分享优质竞赛项目,今天要分享的是 🚩 GRU的 电影评论情感分析 - python 深度学习 情感分类 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分工作量:3分创新点:4分 这…

git常用命令和开发常用场景

git命令 git init 创建一个空的git仓库或者重新初始化已有仓库 git clone [url] 将存储库克隆到新目录 git add 添加内容到索引 git status 显示工作树状态 git commit -m "" 记录仓库的修改 git reset 重置当前HEAD到指定的状态 git reset –-soft:…

【Java学习之道】Java常用集合框架

引言 在Java中,集合框架是一个非常重要的概念。它提供了一种方式,让你可以方便地存储和操作数据。Java中的集合框架包括各种集合类和接口,这些类和接口提供了不同的功能和特性。通过学习和掌握Java的集合框架,你可以更好地管理和…

Response Status Code 301、302

目录 Information Django redirect Influence Information HTTP状态码301、302和304分别表示以下情况: codeinformation301(Moved Permanently) 永久重定向。当请求的资源已经被永久地移动到了一个新的URI时,服务器会返回这个…