我有这个barcodeScannerView。我如何设置它,使相机将立即加载,就像在这个video?
即使我不检查权限,加载摄像头也需要2秒,它显示一个白色屏幕,然后一秒黑色,然后是摄像头,这是一个糟糕的用户体验。我希望用户有一个即时的体验,就像在所附的视频。
class BarcodeScannerView extends StatefulWidget {
@override
State<BarcodeScannerView> createState() => _BarcodeScannerViewState();
}
class _BarcodeScannerViewState extends State<BarcodeScannerView> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final BarcodeScanner _barcodeScanner = BarcodeScanner();
bool _canProcess = true;
bool _isBusy = false;
CustomPaint? _customPaint;
String? _text;
bool _hasNavigated = false;
var _cameraLensDirection = CameraLensDirection.back;
late StreamController<PermissionStatus?> _permissionStatusController;
@override
void initState() {
super.initState();
_permissionStatusController = StreamController<PermissionStatus?>();
_checkAndRequestCameraPermission();
}
@override
void dispose() {
_canProcess = false;
_barcodeScanner.close();
_permissionStatusController.close();
super.dispose();
}
Future<void> _checkAndRequestCameraPermission() async {
PermissionStatus status = await Permission.camera.status;
if (!status.isGranted) {
status = await Permission.camera.request();
}
_permissionStatusController.add(status);
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: StreamBuilder<PermissionStatus?>(
stream: _permissionStatusController.stream,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.data == PermissionStatus.granted) {
return _buildCameraView();
} else {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('הרשאות המצלמה נדחו'),
SizedBox(height: 16),
ElevatedButton(
onPressed: () => openAppSettings(),
child: Text('אפשר הרשאות מצלמה'),
),
],
),
);
}
} else {
return Center(child: CircularProgressIndicator());
}
},
),
);
}
Widget _buildCameraView() {
return DetectorView(
title: 'Barcode Scanner',
customPaint: _customPaint,
text: _text,
onImage: _checkAndProcessImage,
initialCameraLensDirection: _cameraLensDirection,
onCameraLensDirectionChanged: (value) => _cameraLensDirection = value,
);
}
Future<void> _checkAndProcessImage(InputImage inputImage) async {
if (!_canProcess) return;
if (_isBusy) return;
// Camera permission is granted, proceed to process the image
_isBusy = true;
setState(() {
_text = '';
});
final barcodes = await _barcodeScanner.processImage(inputImage);
if (inputImage.metadata?.size != null &&
inputImage.metadata?.rotation != null) {
for (final barcode in barcodes) {
print('Scanned Barcode: ${barcode.rawValue}');
// Navigate to the new screen with the barcode value
if (!_hasNavigated &&
(barcode.format == BarcodeFormat.upca ||
barcode.format == BarcodeFormat.ean13 ||
barcode.format == BarcodeFormat.upce)) {
_hasNavigated = true;
HapticFeedback.vibrate();
showModalBottomSheet(
context: _scaffoldKey.currentContext!,
isScrollControlled: true,
builder: (context) => DraggableScrollableSheet(
expand: false,
initialChildSize: 0.3,
maxChildSize: 0.85,
builder: (context, scrollController) => ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Scaffold(
body: ProductDetailsView(
barcodeValue: barcode.rawValue ?? '',
scrollController: scrollController,
),
),
),
),
).whenComplete(() {
ScaffoldMessenger.of(context).removeCurrentSnackBar();
_hasNavigated = false;
});
}
}
final painter = BarcodeDetectorPainter(
barcodes,
inputImage.metadata!.size,
inputImage.metadata!.rotation,
_cameraLensDirection,
);
_customPaint = CustomPaint(painter: painter);
} else {
String text = 'Barcodes found: ${barcodes.length}\n\n';
for (final barcode in barcodes) {
text += 'Barcode: ${barcode.rawValue}\n\n';
}
_text = text;
_customPaint = null;
}
_isBusy = false;
if (mounted) {
setState(() {});
}
}
}
字符串
下面是cameraView和detectorView的代码
我从主页bottomNavigationBar调用barcodeScannerView,如下所示:
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _currentIndex = 0;
final List<Widget> _screens = [
BarcodeScannerView(),
HistoryScreen(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: _screens[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.barcode_reader),
label: 'Scan,
),
BottomNavigationBarItem(
icon: Icon(Icons.history),
label: 'History,
),
],
),
);
}
}
型
1条答案
按热度按时间igetnqfo1#
将摄像头初始化逻辑移到小部件生命周期的稍后阶段,这样它就不会影响初始构建。
您可以在BarcodeScannerView的initState中初始化摄像头,甚至更晚,例如,当用户点击扫描按钮时。
字符串
考虑在后台初始化相机,同时显示启动画面或加载指示器。
型