- 问题: MaterialApp的Title是干嘛的?
- 来由
- 去除Tabbar的Material Design点击效果
- AppBar去除底部阴影
- Bottom overflowed by xx pixels 问题
- JsonToDart工具
- iOS模拟器中无法弹出键盘的问题
- initalRoute和home属性为什么不建议同时使用
- Cannot fit requested classes in a single dex file (# methods: 74083 > 65536)
- 点击空白处取消TextField、TextFormField焦点
- Vertical viewport was given unbounded height
- 键盘类型选择中开启小数点键盘
- 对TextField,TextFormField设置输入格式约束
问题: MaterialApp的Title是干嘛的?
来由
当查看代码是,发现MaterialApp也包含一个title的属性,这个值修改后,没有引起UI界面上任何改变。
遂有疑问:MaterialApp的title是干嘛用的?
在网上,也查到了相应的疑问,但被选中的回答并不完全正确。
https://stackoverflow.com/questions/50615006/where-does-the-title-of-material-app-used-in-flutter
import 'package:flutter/material.dart';
import 'views/counter.dart';
import 'common/utils.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false, // 用户设置取消右上角debug样式
title: 'Flutter Demo', // 这个title的作用是什么?
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Tentative'),
);
}
}
在进入到MaterialApp的源码中(app.dart)查看时,看到下面的这段话:
结合 onGenerateTitle
分析,这个方法是可以动态生成App title的。那么 final String title;
这段代码即表示 WidgetsApp的固定title属性。其他用途,后续遇到再分析吧。
去除Tabbar的Material Design点击效果
在TabBar的外层套一个Theme Widget
将Theme改为透明即可
https://www.codeleading.com/article/61775510629/
AppBar去除底部阴影
elevation: 0, //去掉Appbar底部阴影
Bottom overflowed by xx pixels 问题
处理这个问题:
- 可以使用 SingleChildScrollView 组件
- 直接在 Scaffold里添加 resizeToAvoidBottomInset = false
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勾选掉即可
initalRoute和home属性为什么不建议同时使用
这个问题在官方文档上有明确的warning提示:
NOTE:但实际使用中即使同时也还OK(TBD)
在stackoverflow中有明确的说明:
https://stackoverflow.com/questions/61764803/difference-between-initialroute-and-home-in-materialapp
Cannot fit requested classes in a single dex file (# methods: 74083 > 65536)
出现这样的问题一般都是项目逐渐变大的情况下产生的。(指向Android模拟器启动时)
解决这样的问题需要在flutter项目的Android项目中找到 app下的build.gradle
添加:mulitDexEnable
为 true
即可。
点击空白处取消TextField、TextFormField焦点
在最外层使用GestureDetector,并设置onTap方法为:FocusScope.of(context).unfocus();
即可。
Vertical viewport was given unbounded height
当widget直接返回 listview 或 listview.builder的时候,容易发生这样的问题。
当listview被container组件包裹的时候,可以为container设置一个高度,或者,将listview的属性:shrinkWrap 设置为 true。
键盘类型选择中开启小数点键盘
在flutter中使用TextField或TextFormField的时候,需要设置键盘类型,通常的选择如下:
单很多时候,比如,选择number的时候,需要包括小数点后面的数字,默认情况在iOS上,如果选择:
TextInputType.number时,是不带小数点键盘的。
选择如下属性可以设置iOS开启包含小数点的键盘。keyboardType: TextInputType.numberWithOptions(decimal: true)
对TextField,TextFormField设置输入格式约束
采用属性:inputFormatters: []
它接受一个格式数组用来对输入框进行约束。
例如 - 限制输入数据整数部分上限及保留小数点后x位的格式如下:integerLength = 5
表示整数部分限制输入5位数,decimalLength = 2
表示小数点后保留两位。
class WithdrawAmountFormatter extends TextInputFormatter {
int integerLength;
int decimalLength;
// bool? allowInputDecimal;
WithdrawAmountFormatter({this.integerLength = 5, this.decimalLength = 2}) : super();
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
String value = newValue.text;
int selectionIndex = newValue.selection.end;
if (newValue.text.contains('.')) {
int pointIndex = newValue.text.indexOf('.');
String beforePoint = newValue.text.substring(0, pointIndex);
//小数点前内容大于integerLength
if (beforePoint.length > integerLength) {
value = oldValue.text;
selectionIndex = oldValue.selection.end;
} else
//小数点前内容小于等于integerLength
{
String afterPoint = newValue.text.substring(pointIndex + 1, newValue.text.length);
if (afterPoint.length > decimalLength) {
value = oldValue.text;
selectionIndex = oldValue.selection.end;
}
}
} else {
if (newValue.text.length > integerLength) {
value = oldValue.text;
selectionIndex = oldValue.selection.end;
}
}
return new TextEditingValue(
text: value,
selection: new TextSelection.collapsed(offset: selectionIndex),
);
}
}