Я новичок во Flutter и пытаюсь изменить существующий пример флаттера для библиотеки flutter-nordi c -dfu (https://github.com/fengqiangboy/flutter-nordic-dfu). Пример работает нормально, и я могу заставить его загрузить прошивку DFU, но (по крайней мере, на Android) он открывает индикатор выполнения уведомлений. Я не думаю, что это особенно "удобно для пользователя", так как вам нужно потянуть вниз сверху, чтобы увидеть ход уведомления.
Я не против, чтобы ход окна уведомлений отображался, но я бы предпочел, чтобы прогресс был показан на оверлее окна во время загрузки. Библиотека возвращает процент загруженных данных в окне отладки.
Есть ли простой способ показать прогресс во всплывающем окне, которое появляется во время загрузки и исчезает после завершения? Я бы предпочел, чтобы пользователь не вмешивался, если это возможно (при загрузке ничего не кликабельно). Я читал об использовании модального окна, которое должно блокировать ввод пользователя, но не уверен, что это самый простой / элегантный способ. Ниже приведен пример в формате gif того, что я представляю, когда вы нажимаете «Начать Dfu», за исключением того, что индикатор выполнения будет показывать процент обновления: https://i.stack.imgur.com/DjRl2.gif
Благодарю за любую помощь что можно предложить. Существующий пример кода ниже:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_nordic_dfu/flutter_nordic_dfu.dart';
import 'package:flutter_blue/flutter_blue.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final FlutterBlue flutterBlue = FlutterBlue.instance;
StreamSubscription<ScanResult> scanSubscription;
List<ScanResult> scanResults = <ScanResult>[];
bool dfuRunning = false;
@override
void initState() {
super.initState();
}
Future<void> doDfu(String deviceId) async {
stopScan();
dfuRunning = true;
try {
var s = await FlutterNordicDfu.startDfu(
deviceId,
'assets/file.zip',
fileInAsset: true,
progressListener:
DefaultDfuProgressListenerAdapter(onProgressChangedHandle: (
deviceAddress,
percent,
speed,
avgSpeed,
currentPart,
partsTotal,
) {
print('deviceAddress: $deviceAddress, percent: $percent');
}),
);
print(s);
dfuRunning = false;
} catch (e) {
dfuRunning = false;
print(e.toString());
}
}
void startScan() {
scanSubscription?.cancel();
setState(() {
scanResults.clear();
scanSubscription = flutterBlue.scan().listen(
(scanResult) {
if (scanResults.firstWhere(
(ele) => ele.device.id == scanResult.device.id,
orElse: () => null) !=
null) {
return;
}
setState(() {
/// add result to results if not added
scanResults.add(scanResult);
});
},
);
});
}
void stopScan() {
scanSubscription?.cancel();
scanSubscription = null;
setState(() => scanSubscription = null);
}
@override
Widget build(BuildContext context) {
final isScanning = scanSubscription != null;
final hasDevice = scanResults.length > 0;
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
actions: <Widget>[
isScanning
? IconButton(
icon: Icon(Icons.pause_circle_filled),
onPressed: dfuRunning ? null : stopScan,
)
: IconButton(
icon: Icon(Icons.play_arrow),
onPressed: dfuRunning ? null : startScan,
)
],
),
body: !hasDevice
? const Center(
child: const Text('No device'),
)
: ListView.separated(
padding: const EdgeInsets.all(8),
itemBuilder: _deviceItemBuilder,
separatorBuilder: (context, index) => const SizedBox(height: 5),
itemCount: scanResults.length,
),
),
);
}
Widget _deviceItemBuilder(BuildContext context, int index) {
var result = scanResults[index];
return DeviceItem(
scanResult: result,
onPress: dfuRunning
? null
: () async {
await this.doDfu(result.device.id.id);
},
);
}
}
class ProgressListenerListener extends DfuProgressListenerAdapter {
@override
void onProgressChanged(String deviceAddress, int percent, double speed,
double avgSpeed, int currentPart, int partsTotal) {
super.onProgressChanged(
deviceAddress, percent, speed, avgSpeed, currentPart, partsTotal);
print('deviceAddress: $deviceAddress, percent: $percent');
}
}
class DeviceItem extends StatelessWidget {
final ScanResult scanResult;
final VoidCallback onPress;
DeviceItem({this.scanResult, this.onPress});
@override
Widget build(BuildContext context) {
var name = "Unknow";
if (scanResult.device.name != null && scanResult.device.name.length > 0) {
name = scanResult.device.name;
}
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Icon(Icons.bluetooth),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(name),
Text(scanResult.device.id.id),
Text("RSSI: ${scanResult.rssi}"),
],
),
),
FlatButton(onPressed: onPress, child: Text("Start Dfu"))
],
),
),
);
}
}`