问题: MaterialApp的Title是干嘛的?

来由

当查看代码是,发现MaterialApp也包含一个title的属性,这个值修改后,没有引起UI界面上任何改变。
遂有疑问:MaterialApp的title是干嘛用的?
在网上,也查到了相应的疑问,但被选中的回答并不完全正确。
https://stackoverflow.com/questions/50615006/where-does-the-title-of-material-app-used-in-flutter
image.png

  1. import 'package:flutter/material.dart';
  2. import 'views/counter.dart';
  3. import 'common/utils.dart';
  4. void main() => runApp(MyApp());
  5. class MyApp extends StatelessWidget {
  6. // This widget is the root of your application.
  7. @override
  8. Widget build(BuildContext context) {
  9. return MaterialApp(
  10. debugShowCheckedModeBanner: false, // 用户设置取消右上角debug样式
  11. title: 'Flutter Demo', // 这个title的作用是什么?
  12. theme: ThemeData(
  13. // This is the theme of your application.
  14. //
  15. // Try running your application with "flutter run". You'll see the
  16. // application has a blue toolbar. Then, without quitting the app, try
  17. // changing the primarySwatch below to Colors.green and then invoke
  18. // "hot reload" (press "r" in the console where you ran "flutter run",
  19. // or simply save your changes to "hot reload" in a Flutter IDE).
  20. // Notice that the counter didn't reset back to zero; the application
  21. // is not restarted.
  22. primarySwatch: Colors.blue,
  23. ),
  24. home: MyHomePage(title: 'Flutter Tentative'),
  25. );
  26. }
  27. }

在进入到MaterialApp的源码中(app.dart)查看时,看到下面的这段话:
image.png

结合 onGenerateTitle 分析,这个方法是可以动态生成App title的。那么
final String title; 这段代码即表示 WidgetsApp的固定title属性。其他用途,后续遇到再分析吧。

去除Tabbar的Material Design点击效果

image.png
在TabBar的外层套一个Theme Widget
将Theme改为透明即可
https://www.codeleading.com/article/61775510629/

AppBar去除底部阴影

elevation: 0, //去掉Appbar底部阴影

Bottom overflowed by xx pixels 问题

处理这个问题:

  1. 可以使用 SingleChildScrollView 组件
  2. 直接在 Scaffold里添加 resizeToAvoidBottomInset = false

image.png
image.png

JsonToDart工具

用于(或限于国内IT环境下前端与后端的对接场景)将后端返回的(不规则的)JSON数据格式转换为可用的Dart对象。
https://github.com/fluttercandies/JsonToDart

国外使用比较多的是基于这个视频上介绍的处理方法:
官方:https://flutter.cn/docs/development/data-and-backend/json#code-generation
油管:https://www.youtube.com/watch?v=8fFoLs9qVQA

iOS模拟器中无法弹出键盘的问题

选择Simulator -> I/O -> Keyboard -> Connect Hardware Keyboard勾选掉即可
image.png

initalRoute和home属性为什么不建议同时使用

这个问题在官方文档上有明确的warning提示:
image.png

NOTE:但实际使用中即使同时也还OK(TBD)

在stackoverflow中有明确的说明:
https://stackoverflow.com/questions/61764803/difference-between-initialroute-and-home-in-materialapp
image.png

Cannot fit requested classes in a single dex file (# methods: 74083 > 65536)

出现这样的问题一般都是项目逐渐变大的情况下产生的。(指向Android模拟器启动时)
image.png
解决这样的问题需要在flutter项目的Android项目中找到 app下的build.gradle
image.pngimage.png
添加:mulitDexEnabletrue 即可。

点击空白处取消TextField、TextFormField焦点

在最外层使用GestureDetector,并设置onTap方法为:
FocusScope.of(context).unfocus(); 即可。
image.png

Vertical viewport was given unbounded height

当widget直接返回 listview 或 listview.builder的时候,容易发生这样的问题。
当listview被container组件包裹的时候,可以为container设置一个高度,或者,将listview的属性:shrinkWrap 设置为 true。
image.png

键盘类型选择中开启小数点键盘

在flutter中使用TextField或TextFormField的时候,需要设置键盘类型,通常的选择如下:
image.png
单很多时候,比如,选择number的时候,需要包括小数点后面的数字,默认情况在iOS上,如果选择:
TextInputType.number时,是不带小数点键盘的。
选择如下属性可以设置iOS开启包含小数点的键盘。
keyboardType: TextInputType.numberWithOptions(decimal: true)

对TextField,TextFormField设置输入格式约束

采用属性:inputFormatters: []
它接受一个格式数组用来对输入框进行约束。

例如 - 限制输入数据整数部分上限及保留小数点后x位的格式如下:
integerLength = 5 表示整数部分限制输入5位数,decimalLength = 2 表示小数点后保留两位。

  1. class WithdrawAmountFormatter extends TextInputFormatter {
  2. int integerLength;
  3. int decimalLength;
  4. // bool? allowInputDecimal;
  5. WithdrawAmountFormatter({this.integerLength = 5, this.decimalLength = 2}) : super();
  6. @override
  7. TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
  8. String value = newValue.text;
  9. int selectionIndex = newValue.selection.end;
  10. if (newValue.text.contains('.')) {
  11. int pointIndex = newValue.text.indexOf('.');
  12. String beforePoint = newValue.text.substring(0, pointIndex);
  13. //小数点前内容大于integerLength
  14. if (beforePoint.length > integerLength) {
  15. value = oldValue.text;
  16. selectionIndex = oldValue.selection.end;
  17. } else
  18. //小数点前内容小于等于integerLength
  19. {
  20. String afterPoint = newValue.text.substring(pointIndex + 1, newValue.text.length);
  21. if (afterPoint.length > decimalLength) {
  22. value = oldValue.text;
  23. selectionIndex = oldValue.selection.end;
  24. }
  25. }
  26. } else {
  27. if (newValue.text.length > integerLength) {
  28. value = oldValue.text;
  29. selectionIndex = oldValue.selection.end;
  30. }
  31. }
  32. return new TextEditingValue(
  33. text: value,
  34. selection: new TextSelection.collapsed(offset: selectionIndex),
  35. );
  36. }
  37. }