一.手机振动功能
1.1 引入库
dependencies: flutter: sdk: flutter vibration: ^1.8.4
1.2 在AndroidManifest.xml 中添加权限
</application> <uses-permission android:name="android.permission.VIBRATE"/>
1.3 代码实例--在main.dart里
import 'package:flutter/material.dart';
import 'package:vibration/vibration.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Vibration Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 在主页加载时执行震动功能
vibrateDevice();
return Scaffold(
appBar: AppBar(
title: const Text('Vibration Demo'),
),
body: Center(
child: Text(
'手机正在震动...',
style: TextStyle(fontSize: 20),
),
),
);
}
Future<void> vibrateDevice() async {
bool? canVibrate = await Vibration.hasVibrator();
if (canVibrate != null && canVibrate) {
Vibration.vibrate(duration: 1000); // 震动1秒钟
} else {
print('设备不支持震动功能');
}
}
}
二. 警报弹窗
2.1 代码示例
在main.dart里
我用if语句写了等级判断,设定了危险阈值,当到达阈值时,会触发报警弹窗。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fire Detection System',
home: SensorMonitoringPage(),
);
}
}
class SensorMonitoringPage extends StatefulWidget {
@override
_SensorMonitoringPageState createState() => _SensorMonitoringPageState();
}
class _SensorMonitoringPageState extends State<SensorMonitoringPage> {
final double temperature = 75.5; // 温度
final double smokeDensity = 30.0; // 烟雾浓度
final double flameSize = 0.7; // 火焰大小
final String location="A501";
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_evaluateFireLevel();
});
}
String _evaluateFireLevel() {
String fireLevel;
if (temperature >= 80.0 || smokeDensity >= 50.0 || flameSize >= 0.8) {
fireLevel = '一级火灾';
} else if (temperature >= 70.0 || smokeDensity >= 30.0 || flameSize >= 0.5) {
fireLevel = '二级火灾';
} else if (temperature >= 60.0 || smokeDensity >= 20.0 || flameSize >= 0.3) {
fireLevel = '三级火灾';
} else {
fireLevel = '无火灾';
}
if (fireLevel != '无火灾') {
_showAlert(fireLevel);
}
return fireLevel;
}
void _showAlert(String fireLevel) {
showDialog(
barrierDismissible: false, //表示点击灰色背景的时候是否消失弹出框
context: context,
builder: (BuildContext context) {
return
AlertDialog(
title: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.warning, size:40,color: Colors.red), // 警告标志
SizedBox(width: 8), // 警告标志与标题之间的间距
Text('火灾警报'),
// 对话框标题
],
),
content: SingleChildScrollView(
child:
ListBody(
children: <Widget>[
ListTile(title: Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
ListTile(title: Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
ListTile(title: Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
ListTile(title: Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
ListTile(title:Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
ListTile(title:Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
ListTile(title: Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
ListTile(title: Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
ListTile(title: Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
ListTile(title: Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
ListTile(title:Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
ListTile(title:Text('在$location发生$fireLevel,现场温度为$temperature,烟雾浓度为$smokeDensity',)),
],
),
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('关闭'),
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Sensor Monitoring'),
),
body: Center(
child: Text('Monitoring Page Content'),
),
);
}
}
2.2 结果
三. 按钮跳转报警页面
3.1 引入库
url_launcher: ^6.2.5
3.2 插入两个按钮
TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.zero, // 移除内边距
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
minimumSize: Size(55, 55 + 10 + 16), // 宽度和高度
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // 紧缩点击区域到最小
backgroundColor: Colors.grey, // 按钮背景颜色
// primary: Colors.black, // 文本颜色
textStyle: TextStyle(fontSize: 16),
),
onPressed: () {
_makePhoneCall("119");
},
child: Column(
mainAxisSize: MainAxisSize.min, // 控制大小
children: <Widget>[
Container(
height: 55,
width: 55,
decoration: BoxDecoration(
color: Colors.red,
border: Border.all(color: Colors.black12, width: 1),
borderRadius: BorderRadius.circular(20),
),
child: Icon(
Icons.phone,
size: 30,
color: Colors.white,
),
),
SizedBox(height: 10),
Text('紧急SOS',style: TextStyle(color: Colors.black, fontSize: 16)),
],
),
),
TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.zero, // 移除内边距
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
minimumSize: Size(55, 55 + 10 + 16), // 宽度和高度
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // 紧缩点击区域到最小
backgroundColor: Colors.grey, // 按钮背景颜色
// primary: Colors.black, // 文本颜色
textStyle: TextStyle(fontSize: 16),
),
onPressed: () {
_openSMSApp();
},
child: Column(
mainAxisSize: MainAxisSize.min, // 控制大小
children: <Widget>[
Container(
height: 55,
width: 55,
decoration: BoxDecoration(
color: Colors.yellow,
border: Border.all(color: Colors.black12, width: 1),
borderRadius: BorderRadius.circular(20),
),
child: Icon(
Icons.message,
size: 30,
color: Color.fromARGB(255, 183, 119, 194),
),
),
SizedBox(height: 10),
Text('紧急MSM',style: TextStyle(color: Colors.black, fontSize: 16)),
],
),
),
3.3 SOS和MSM
oid _openSMSApp() async {
String uri = 'sms:';
if (0 == 0) {
await launch(uri);
} else {
throw 'Could not launch $uri';
}
}
void _makePhoneCall(String phoneNumber) async {
String uri = 'tel:$phoneNumber';
if (await launchUrl(Uri.parse("tel:119"))) {
await launch(uri);
} else {
throw 'Could not launch $uri';
}
}
3.4 结果
四、 等级消防器械信息
4.1 导入库
intl: ^0.19.0
4.2 示例代码
当当前日期超过更换日期时会产生弹窗提醒。
import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; // 用于格式化日期
class DateEntryPage extends StatefulWidget {
@override
_DateEntryPageState createState() => _DateEntryPageState();
}
class _DateEntryPageState extends State<DateEntryPage> {
DateTime? productionDate;
DateTime? replacementDate;
TextEditingController productionDateController = TextEditingController();
TextEditingController replacementDateController = TextEditingController();
@override
void initState() {
super.initState();
// 初始化日期控制器,用于显示已保存的日期
productionDateController.text = productionDate != null ? DateFormat('yyyy-MM-dd').format(productionDate!) : '';
replacementDateController.text = replacementDate != null ? DateFormat('yyyy-MM-dd').format(replacementDate!) : '';
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('消防器械日期管理'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: productionDateController,
readOnly: true,
decoration: InputDecoration(
labelText: '生产日期',
suffixIcon: IconButton(
icon: Icon(Icons.calendar_today),
onPressed: () async {
// 显示日期选择器,并将选中日期更新到控制器中
DateTime? picked = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2000),
lastDate: DateTime.now(),
);
if (picked != null && picked != productionDate) {
setState(() {
productionDate = picked;
productionDateController.text = DateFormat('yyyy-MM-dd').format(productionDate!);
});
}
},
),
),
),
SizedBox(height: 20),
TextField(
controller: replacementDateController,
readOnly: true,
decoration: InputDecoration(
labelText: '更换日期',
suffixIcon: IconButton(
icon: Icon(Icons.calendar_today),
onPressed: () async {
// 显示日期选择器,并将选中日期更新到控制器中
DateTime? picked = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2000),
lastDate: DateTime.now().add(Duration(days: 365 * 10)), // 最多选择10年后的日期
);
if (picked != null && picked != replacementDate) {
setState(() {
replacementDate = picked;
replacementDateController.text = DateFormat('yyyy-MM-dd').format(replacementDate!);
});
}
},
),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// 模拟保存日期,这里可以将日期保存到本地或者数据库中
// 保存逻辑可以根据实际需求进行扩展
if (productionDate != null && replacementDate != null) {
// 检查日期是否已过期
if ( DateTime.now().isAfter(replacementDate!)) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('提醒'),
content: Text('当前日期已超过录入日期'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('确定'),
),
],
);
},
);
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('提醒'),
content: Text('日期保存成功'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('确定'),
),
],
);
},
);
}
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('提醒'),
content: Text('请先选择生产日期和更换日期'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('确定'),
),
],
);
},
);
}
},
child: Text('保存日期'),
),
],
),
),
);
}
}