Flutter小技巧底部弹窗布局大小调整AndroidiOS可运行
本头条核心宗旨
欢迎来到「技术刚刚好」作者,「技术刚刚好」是个人维护,每天至少更新一篇Flutter技术文章,实时为大家播报Flutter最新消息。如果你刚好也在关注Flutter这门技术,那就跟我一起学习进步吧,你的赞,收藏,转发是对我个人最大的支持,维护不易,欢迎关注。技术刚刚好经历
近几年,移动端跨平台开发技术层出不穷,从Facebook家的ReactNative,到阿里家WEEX,前端技术在移动端跨平台开发中大展身手,技术刚刚好作为一名Android开发,经历了从Reactjs到Vuejs的不断学习。而在2018年,我们的主角变成了Flutter,这是Goolge开源的一个移动端跨平台解决方案,可以快速开发精美的移动App。希望跟大家一起学习,一起进步!本文核心要点
本文会带大家学习布局调整的问题,我会以一个具体的实例来讲解本文的内容,首先会写一段代码引出本文要讲解的问题,然后在带大家一起解决它,干货满满,欢迎点赞,收藏。
在我工作当中有一次突然遇到这样一个问题,我们将在这篇文章当中来讨论并解决它。我将带大家用Flutter文档和 dart 带的工具,教大家来解决问题。
本文会学习BoxConstraints,ModalBottomSheet,Align,Stack,Positioned的一些窗口小部件。
我相信大家做移动APP开发从底部弹出一个菜单已经并不陌生了。在Flutter当中已经提供了一个API来。showModalBottomSheet方法。
这种对话框我们项目用到的比较多,所以我们应该创建一个类来封装它。import "package:flutter/material.dart"; Future showBottomDialog({ @required BuildContext context, String title, String content, Widget titleWidget, Widget contentWidget, List actions, bool allowBackNavigation = false, }) { assert(title != null || titleWidget != null, "title and titleWidget both must not be null"); assert(content != null || contentWidget != null, "content and contentWidget both must not be null"); final theme = Theme.of(context); return showModalBottomSheet( context: context, shape: RoundedRectangleBorder( borderRadius: const BorderRadius.only( topLeft: Radius.circular(24), topRight: Radius.circular(24), ), ), isDismissible: allowBackNavigation, builder: (context) => WillPopScope( onWillPop: () async => allowBackNavigation, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32), child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ titleWidget ?? Text( title, textAlign: TextAlign.left, style: Theme.of(context).textTheme.headline2, ), SizedBox(height: 16), contentWidget ?? Text( content, textAlign: TextAlign.left, style: Theme.of(context) .textTheme .bodyText2 .copyWith(height: 1.5), ), SizedBox(height: 48), if (actions != null) ...actions else OutlineButton( child: Text("GOT IT!"), borderSide: BorderSide(color: theme.primaryColor), onPressed: () { Navigator.of(context).pop(); }, ), ], ), ), ), ); } 然后,使用该包装器函数变得很容易,如下所示: class DialogExample extends StatelessWidget { void _showDialog(BuildContext context) { showBottomDialog( context: context, allowBackNavigation: true, title: "Do you wish to purchase add-ons?", content: "Add-ons help you save some extra money when you purchase them along with our original products. Plus, they help your chances of winning as well.", actions: [ RaisedButton( child: Text("YES, GO AHEAD"), onPressed: () {}, ), FlatButton( child: Text("SKIP"), onPressed: () {}, ) ], ); } @override Widget build(BuildContext context) { return Container( child: Center( child: RaisedButton( child: Text("Show Dialog"), onPressed: () => _showDialog(context), ), ), ); } }
这个时候我们就遇到一个问题了,这个时候我们要添加一个IconButton来关闭对话框,这个时候我们可以定义一个isDismissable:true来设置该对话框的关闭或者打开。然后添加一个按钮。Stack( children : [ Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ titleText, contentText, if(_mutipleCTAButtons_ != null) ..._multipleCTAButtons, else commonCTAButton ] ), if(closeButton) Align( alignment : Alignment.topRight, child : IconButton( icon: Icon( Icons.close, size: 24, ), onPressed: onClose ?? () => Navigator.pop(context), ) ) ] )
对showBottomDialog函数的更改如下Future showBottomDialog({ @required BuildContext context, String title, String content, Widget titleWidget, Widget contentWidget, List actions, bool allowBackNavigation = false, bool showCloseButton = false, Function onClose, }) { assert(title != null || titleWidget != null, "title and titleWidget must not both be null"); assert(content != null || contentWidget != null, "content and contentWidget must not both be null"); final theme = Theme.of(context); return showModalBottomSheet( ... builder: (context) => WillPopScope( onWillPop: () async => allowBackNavigation, child: Stack( children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32), child: Column( ... ... // Removed for brevity ], ), ), if (showCloseButton) Align( alignment : Alignment.topRight, child: IconButton( icon: Icon(Icons.close), onPressed: onClose ?? () => Navigator.pop(context), ), ), ], ), ), ); }
然后使用示例上面的使用方面的更改变为:class DialogExample extends StatelessWidget { void _showDialog(BuildContext context) { showBottomDialog( ... ... showCloseButton : true, ); } }
这个时候显示效果如下
这个时候问题就出现了,布局占据了屏幕的高度,差不多屏幕一半高了,是什么原因了,这个时候我们用Dart开发工具来找问题。
首先让我们看看哪个Widget通过打开Dart DevTools导致BottomSheet的高度增加,而无需假定它必须与IconButton对齐,因为添加它是导致问题的原因,对吗?
高亮区域代表我们的BottomSheet的布局层次结构。让我们在DevTool中打开" 选择小部件"模式,然后开始选择小部件,以查看哪个小部件占用了布局空间。
阅读Flutter文档
在开始阅读文档之前,我们先来看一下StackDevTools中的尺寸(宽度和高度)。
可以看出,这些尺寸是具有约束条件的,而我们有没有设置约束,所以其中minWidth和maxWidth分别设置为和分别等于screenWidth和不设置为" 0"和" screenWidth"(即0.0<=w<=414),这意味着明确要求它占据整个屏幕宽度,而不考虑其子级的宽度。而且,maxHeight精确地设置为9/16的screenHeight。结果,Stack的大小被设置为w = 414(screenWidth)和h = 504(screenHeight),这意味着它占据了允许的整个高度。
因此,我们的BottomSheet约束设置如下:final minWidth = constraints.maxWidth; final maxWidth = constraints.maxWidth
小米MIX4发布会时长3小时,雷军请大家做好准备明天就是小米MIX4手机的发布日期了,此前的消息称此次小米MIX4发布会的时长会在1个小时左右,但今天雷军发文称发布会时间会在3个小时左右,请大家做好准备。根据之前的消息来看,小米
丰田再出SUV爆款,48小时订单破万,汉兰达地位恐受威胁如果说有哪一款车最能代表日系品牌在中国的形象,那一定是皇冠。皇冠品牌的历史要追溯到上个世纪50年代,为了满足日本本土日益旺盛的用车需求,丰田公司开始研发皇冠品牌汽车,1955年1月
可怕!共享充电宝竟涨到10元小时!网友怪不得充电速度这么慢如今大街小巷各种店铺里,都摆着借充电宝的机器。据数据统计,在2020年全国在线共享充电宝设备量已超过440万,用户规模超过2亿人。用户是越来越多了,出现的问题也随之显现。1。价格飞
万亿宁德时代,遮蔽下的隐秘能源帝国钠离子电池和其背后的储能市场是宁德时代下一个万亿市值的突破口。撰文新队编辑东篱破万亿当首富,5月以来宁德时代(300750。SZ)和掌门人曾毓群频现报端,成为产业界和资本界备受关注
家装新风系统无忧空气质量随着人们生活水平的逐步提高,无尘环境空气净化等技术逐渐应用到家用新风系统中,家用新风主要有两大基本功能一是促进室内外空气流通循环二是过滤室外富氧空气夹杂的灰尘汽车尾气等颗粒污染物。
两高一低的新风系统,轻松解决室内空气问题使用新风的目的就是期望能够呼吸到富氧干净的空气,所以在选择新风系统是要能明确判断新风系统的效果,一是充足的风量,二是能够净化输送至室内的空气。此外,还需要注意新风系统工作时所产生的
主力资金63亿抢筹有色股!紫金矿业净流入15亿大盘数据今日两市全天上涨1951家,下跌2370家,145家平盘。涨停数93家,跌停4家。沪指上涨0。49,总成交额6794。65亿元深成指微涨0。07,总成交额7526。90亿元
主力资金(9月24日)66亿抢筹饮料股!贵州茅台净流入27亿大盘数据今日两市全天上涨986家,下跌3446家,53家平盘。涨停数51家,跌停63家。沪指下跌0。80,总成交额6067。89亿元深成指微跌0。21,总成交额6766。05亿元创
对标光伏!风能赛道精选高增长企业出炉9月23日,风电板块再次上涨,截至发文,概念股国电电力中闽能源浙江新能华能国际上海电力大唐发电内蒙华电涨停板块共16只股涨超5。驭风计划再次提出,分布式风电需求有望提升9月10日,
依旧是升级雷柏M200Plus静音鼠标小测科技以换壳为本这一说法被雷柏反了过来,最近推出的一系列产品都是遵循的旧瓶装新酒的原则,又在自家的3500pro布艺鼠标的基础上推出了升级产品M200Plus静音鼠标。一。开箱及外观
汽车互联网入口之争再起账号体系依然是打造汽车生态的重中之重。文东篱资本狂热追逐电动汽车与自动驾驶之时,智能网联当中的车联网似乎逐渐被市场遗忘在了角落当中。春节前夕,博泰车联网和上汽通用五菱共同向国家市场