环境:vscode+android studio
碎片
1.appbar了解
2.消息提示库Fluttertoast(非官方)
依赖引入,具体页面使用
//pubspec.yaml
dependencies:
fluttertoast: ^8.2.5
//..具体页面
import 'package:fluttertoast/fluttertoast.dart';
//自定义方法
// 请求响应信息 0 成功 1 失败
void showToast(int flag) {
Fluttertoast.showToast(
msg: (flag == 0) ? "操作成功" : "操作失败!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: (flag == 0)
? Color.fromRGBO(231, 250, 240, 1)
: Color.fromRGBO(255, 237, 237, 1),
textColor: (flag == 0)
? Color.fromRGBO(113, 226, 163, 1)
: Color.fromRGBO(255, 73, 73, 1),
fontSize: 16.0,
);
}
3.RefreshIndicator用于可滚动组件下拉刷新数据
注:需要确保_refreshIndicatorKey.currentState.show() 方法能够正常调用,Container就不行
//刷新页面 调用的方法
child: RefreshIndicator(
onRefresh: () {
return _getList(); // myRefreshFunction是一个返回Future<void>的函数
},
//需要确保这俩都是可下拉的组件
child: total!=0?_buildGrid(): _nullShow()))),
4.有关变量初始化
flutter 在使用未初始化的变量是会报错,所以要在使用前初始化,声明时可用late告诉flutter之后再进行初始化。
5.有关对项目文件及.apk安装后文件的操作:
(1)项目变成.apk安装后其内部(.apk)的文件为只读,不能进行修改,只能进行读操作,该类文件一般需要在pubspec.yaml文件进行声明后才会被打包进包里
//读取项目内pubspec.yaml声明的文件中的内容
try {
final String content =
await rootBundle.loadString('assets/secretkey/31010');
if (content.isEmpty) {
return false; // 文件为空
}
return true; // 文件没找到
} catch (e) {
return false; // 没找到/发生错误
}
(2)在安装完应用程序后会有一个私有存储空间,用来存一些动态可编辑的文件,其来源通常有:
由应用程序内部资源文件生成,应用程序内部资源复制的文件,运行时动态创建或下载的文件,用户产生的数据...
私有存储空间在程序安装到设备时创建,在卸载时销毁,运行时可对其中文件进行读写
6.有关横竖屏适配:
有时候横屏竖屏ui因为种种原因可能会导致显示异常,有两种解决方案
(1)横/竖屏适配
//横竖屏适配true为横屏,false为竖屏
bool screenstatusflag = true;
//获取屏幕状态
MediaQuery.of(context).size.width >
MediaQuery.of(context).size.height
? screenstatusflag= true //横屏
: screenstatusflag= false;// 竖屏
// 使用 MediaQuery 获取设备宽高
final double deviceWidth = MediaQuery.of(context).size.width;
final double deviceHeight = MediaQuery.of(context).size.height;
......
height: screenstatusflag? 500 : deviceHeight * 0.27,
width:screenstatusflag? 900 : deviceWidth * 0.82,
......
Container(
height: screenstatusflag? 500 :deviceHeight * 0.27,
width:screenstatusflag? 590 : deviceWidth * 0.49,
child: Image.asset(
'assets/img/login.png',
fit: BoxFit.contain,
),
2.横/竖屏锁定(强制横/竖屏)
// 强制横屏
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight
]);
// 强制竖屏
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown
]);
问题
1.状态栏颜色设置
设置appbar背景颜色是连同状态栏颜色一起设置了
解决过程:
在初始化方法中调用该方法 会被覆盖,只有一瞬间有变化,后又变回来
正确解决:在appbar中添加
systemOverlayStyle: SystemUiOverlayStyle(
statusBarColor: Colors.red, // 设置状态栏的颜色
),
结果:
2.展示图片
在和lib同目录下创建存图片的文件夹
在pubspec.yaml文件设置存图片文件路径,注意空格
在需要的地方导入,搞完之后重启项目
3.修改对话框在键盘弹出时对话框变形
原因:
解决:使用ListView
4.
展开后下拉框挤到对话框边缘,且方角难看
尝试:
(1)
直接在DropdownButtonFormField外套Container改不受影响
(2)尝试在items返回的值中套Container
items: departmentList .map<DropdownMenuItem<String>>((dynamic value) {
return DropdownMenuItem<String>(
value: value,
child: Container(
decoration: BoxDecoration(
color: Colors
.blueAccent, // 设置单元格的背景颜色
borderRadius:
BorderRadius.circular(
12), // 设置圆角
),
width: 100, // 设置宽度为200
height: 60, // 设置高度为50
child: Text(
value,
style: TextStyle(
color: Colors.black),
),
),
);
})
.toSet()
.toList(),
改后
(3)尝试更换PopupMenuButton作为下拉框
PopupMenuButton( onSelected: (String newValue) {
setState(() {
dropdownValue = newValue;
print(
'dropdownValue被更改$dropdownValue');
// department = newValue;
});
},
itemBuilder: (BuildContext context) {
return departmentList
.map((dynamic value) {
return PopupMenuItem<String>(
value: value,
child: Container(
decoration: BoxDecoration(
// color: Colors
// .blueAccent,
borderRadius:
BorderRadius.circular(
18), // 设置圆角
),
width: 100, // 设置宽度为200
height: 40, // 设置高度为50
child: Container(
height: 50,
width: 100,
child: Text(
value,
style: TextStyle(
color: Colors.black),
),
),
),
);
}).toList();
},
child: Text('科室: $dropdownValue'),
// Icon(Icons.arrow_drop_down),
)
发现更改下拉框值后,默认展示值没变..
导致原因没查出来
(4)尝试用SizeBox+DropdownMenu替换
SizedBox(width: 100, // 设置宽度为300
height: 50, // 设置高度为150
child:
DropdownMenu<String>(
width: 300,
menuHeight: 150,
initialSelection: dropdownValue,
onSelected: _onSelect,
dropdownMenuEntries:
_buildMenuList(departmentList),
),
),
效果:
SizeBox该改的是展开项的宽高
5.嵌套对话框直接关闭
showDialog本质新增了一个页面堆栈,使用Navigator进行管理
builder: (BuildContext contextofform) contextofform中含有当前页面路由信息。关闭对话框使用
Navigator.of(contextofform).pop();
嵌套关闭:
//内层
Navigator.of(context).pop();
//外层
Navigator.of(contextofform).pop();
// Navigator.of(context).popUntil((route) => route.isFirst);
直接弹出路由直到第一个路由为止,一般是到登录
7.事件分级:
关注点分离(Separation of Concerns)
通过将事件分级,可以将不同类型的事件处理逻辑分离开来,使得每个模块只关注特定类型的事件。这有助于代码的清晰度和可维护性。
- 应用程序级别的事件:处理与整个应用程序相关的事件,例如应用程序的生命周期、屏幕尺寸或方向变化等。这些事件通常影响整个应用程序的状态或行为。
- 框架级别的事件:处理与 Flutter 框架相关的事件,例如手势识别、渲染树更新等。这些事件通常影响 Flutter 框架如何处理用户交互和界面渲染。
- 小部件级别的事件:处理与具体小部件相关的事件,例如按钮点击、文本输入等。这些事件通常影响单个小部件的行为和状态。
学习:flutter同步页面数据方法
通过setState方法:
这是 Flutter 最简单的状态管理方式之一。通过调用 setState
方法,可以通知 Flutter 框架重新构建当前 Widget 的子树。当数据发生变化时,调用 setState
方法来更新 UI,Flutter 将会根据新的数据重新构建 Widget 树,从而实现页面数据的同步。
原因:在路由跳转前后刷新是有区别的
//正确
//外层
Navigator.of(contextofform).pop();
await getList();
//错误
await getList();
//外层
Navigator.of(contextofform).pop();
未能解决的;
修改数据后页面同步更新失败
控制台有数据输出,且Refresh有效