ساخت چندین بارکد، کد QR و اسکنر DataMatrix با فلوتر برای مدیریت موجودی

اسکن بارکد یک ابزار ضروری برای مدیریت موجودی مدرن است. دقت، کارایی، ردیابی بلادرنگ و صرفه جویی در هزینه را بهبود می بخشد و آن را به بخش مهمی از هر سیستم مدیریت موجودی موثر تبدیل می کند. در این مقاله نحوه ساخت چندین بارکد، کد QR و اسکنر DataMatrix با Flutter برای مدیریت موجودی در اندروید و iOS را نشان خواهیم داد.
پلتفرم های پشتیبانی شده
وابستگی های فلاتر برای برنامه اسکن چند کد استفاده می شود
برای گسترش قابلیتهای پروژه Flutter هدف فراتر از آنچه توسط کتابخانههای اصلی Flutter ارائه شده است، افزونههای Flutter شخص ثالث ضروری هستند. در زیر لیستی از پلاگین های مورد استفاده در این پروژه آمده است:
-
dynamsoft_capture_vision_flutter – یک پلاگین Flutter برای ضبط جریان دوربین موبایل و اسکن بارکدها، کدهای QR، DataMatrix و دیگر نمادهای بارکد 1D/2D اصلی. توسط Dynamsoft ساخته و نگهداری می شود. شما باید برای مجوز آزمایشی Dynamsoft Barcode Reader درخواست دهید و آن را به روز کنید
LICENSE-KEY
که درlib/main.dart
برای اجرای پروژه -
ارائه دهنده – یک بسته بندی در اطراف InheritedWidget. این یک راه آسان برای به اشتراک گذاری داده ها بین ویجت ها در یک برنامه Flutter ارائه می دهد.
-
url_launcher – یک افزونه Flutter برای راه اندازی URL در پلت فرم تلفن همراه.
-
share_plus – یک افزونه Flutter برای به اشتراک گذاری متن و فایل ها از پلت فرم تلفن همراه. توسط fluttercommunity ساخته و نگهداری می شود.
-
image_picker – یک پلاگین Flutter برای iOS و Android برای انتخاب تصاویر از کتابخانه تصویر و گرفتن عکس های جدید با دوربین.
-
flutter_exif_rotation – یک پلاگین Flutter برای چرخاندن تصاویر بر اساس داده های EXIF. این مشکل جهت گیری تصاویر گرفته شده توسط دوربین برخی از دستگاه ها را برطرف می کند.
مراحل ساخت اسکنر چند کد با فلاتر
در قسمت های بعدی مراحل ساخت یک بارکد چندگانه، کد QR و اسکنر DataMatrix با فلاتر را طی می کنیم.
صفحه اصلی
صفحه اصلی از دو دکمه کاشی، یک دکمه تنظیمات و یک نوار زبانه تشکیل شده است. دو دکمه کاشی به ترتیب برای راه اندازی اسکن دوربین و اسکن فایل استفاده می شود. دکمه تنظیمات برای تغییر انواع بارکد است. نوار برگه برای جابجایی بین نمای خانه، نمای تاریخچه و نمای درباره است.
نحوه ایجاد دکمه کاشی
برای ایجاد یک دکمه کاشی که از یک نماد و یک برچسب تشکیل شده است، می توانید از آن استفاده کنید ElevatedButton
ویجت با style
اموال به شکل مربع تنظیم شده است.
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ScannerScreen()),
);
},
style: ElevatedButton.styleFrom(
minimumSize: const Size.square(
64), // Set the size of the button to be square
),
child: Stack(
children: const [
Align(
alignment: Alignment.center,
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'Inventory Scan',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.camera,
color: Colors.white,
),
),
),
],
),
)
برای چیدمان چند دکمه کاشی، می توانید از GridView.count
ویجت با crossAxisCount
دارایی روی 2 تنظیم شده است، mainAxisSpacing
و crossAxisSpacing
ویژگی ها روی 16 تنظیم شده و padding
دارایی روی 16 تنظیم شده است.
child: GridView.count(
crossAxisCount: 2,
mainAxisSpacing: 16,
crossAxisSpacing: 16,
padding: const EdgeInsets.all(16),
children: []),
نحوه اضافه کردن دکمه تنظیمات به نوار وضعیت
دکمه تنظیمات برای تغییر انواع بارکد استفاده می شود. برای افزودن دکمه تنظیمات به نوار وضعیت، می توانید از AppBar
ویجت با actions
ویژگی تنظیم شده به a IconButton
ویجت
AppBar(
title: Text(widget.title),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () async {
var result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SettingsScreen()),
);
},
),
],
)
را result
متغیر انواع بارکد بازگردانده شده از صفحه تنظیمات است. می توانید استفاده کنید Provider
ویجت برای ذخیره مقدار برای دسترسی جهانی.
نحوه اشتراک گذاری انواع بارکد بین ویجت های مختلف یک برنامه Flutter
Flutter Provider یک راه حل مدیریت وضعیت است که به شما امکان می دهد به راحتی وضعیت برنامه Flutter خود را مدیریت کنید. شما به راحتی می توانید داده ها را بین بخش های مختلف برنامه خود به اشتراک بگذارید بدون اینکه نیازی به ارسال آن از طریق زنجیره ای از تماس ها باشد.
در این پروژه، ما باید چندین نوع بارکد و نتیجه تشخیص بارکد را برای ویجت های مختلف در دسترس قرار دهیم. مراحل زیر نحوه استفاده از Provider
ویجت برای اشتراک گذاری وضعیت جهانی:
-
ایجاد یک
ChangeNotifier
کلاس برای ذخیره انواع بارکد و نتیجه تشخیص بارکد.import 'package:dynamsoft_capture_vision_flutter/dynamsoft_capture_vision_flutter.dart'; import 'package:flutter/foundation.dart'; class ScanProvider extends ChangeNotifier { int _types = 0; int get types => _types; set types(int value) { _types = value; notifyListeners(); } final Map<String, BarcodeResult> _results = {}; Map<String, BarcodeResult> get results => _results; void addResult(String key, BarcodeResult result) { _results[key] = result; notifyListeners(); } void clearResults() { _results.clear(); notifyListeners(); } void removeResult(String key) { _results.remove(key); notifyListeners(); } }
-
ایجاد یک
ChangeNotifierProvider
ویجت برای بسته بندیScanProvider
ویجت، و سپس اضافه کنیدScanProvider
ویجت بهMultiProvider
ویجت راMultiProvider
ویجت می تواند شامل چندین مورد باشدChangeNotifierProvider
ویجت هاvoid main() { runApp(MultiProvider(providers: [ ChangeNotifierProvider(create: (_) => SwitchProvider()), ChangeNotifierProvider(create: (_) => ScanProvider()), ], child: const MyApp())); }
را
SwitchProvider
ویجت برای تغییر اندازه دوربین در بخش بعدی استفاده خواهد شد. -
ذخیره انواع بارکد در
ScanProvider
ویجتvar result = await Navigator.push( context, MaterialPageRoute( builder: (context) => const SettingsScreen()), ); Provider.of<ScanProvider>(context).types = result['format'];
نحوه ایجاد نوار برگه
نمای نوار برگه به کاربران امکان می دهد بین نماهای مختلف بدون نیاز به رفت و برگشت بین صفحات مختلف حرکت کنند. برای ایجاد نوار برگه، می توانید از TabBarView
ویجت با children
ویژگی مجموعه به لیستی از Widget
اشیاء.
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: 3);
_initLicense();
}
TabBarView(
controller: _tabController,
children: const [
HomeView(title: 'Dynamsoft Barcode SDK'),
HistoryView(title: 'History'),
InfoView(title: 'About the SDK'),
],
),
صفحه تنظیم نوع بارکد
صفحه تنظیمات برای پیکربندی بارکد خوان Dynamsoft استفاده می شود. در حال حاضر، فقط نماد بارکد پشتیبانی می شود. همچنین می توانید پارامترهای دیگری را برای تنظیم عملکرد SDK اضافه کنید.
class _SettingsScreenState extends State<SettingsScreen> {
bool _is1dChecked = true;
bool _isQrChecked = true;
bool _isPdf417Checked = true;
bool _isDataMatrixChecked = true;
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
int format = 0;
if (_is1dChecked) {
format |= EnumBarcodeFormat.BF_ONED;
}
if (_isQrChecked) {
format |= EnumBarcodeFormat.BF_QR_CODE;
}
if (_isPdf417Checked) {
format |= EnumBarcodeFormat.BF_PDF417;
}
if (_isDataMatrixChecked) {
format |= EnumBarcodeFormat.BF_DATAMATRIX;
}
Navigator.pop(context, {'format': format});
return true;
},
child: Scaffold(
appBar: AppBar(
title: const Text('Settings'),
),
body: ListView(
children: <Widget>[
CheckboxListTile(
title: const Text('1D Barcode'),
value: _is1dChecked,
onChanged: (bool? value) {
setState(() {
_is1dChecked = value!;
});
},
),
CheckboxListTile(
title: const Text('QR Code'),
value: _isQrChecked,
onChanged: (bool? value) {
setState(() {
_isQrChecked = value!;
});
},
),
CheckboxListTile(
title: const Text('PDF417'),
value: _isPdf417Checked,
onChanged: (bool? value) {
setState(() {
_isPdf417Checked = value!;
});
},
),
CheckboxListTile(
title: const Text('DataMatrix'),
value: _isDataMatrixChecked,
onChanged: (bool? value) {
setState(() {
_isDataMatrixChecked = value!;
});
},
),
],
),
),
);
}
}
را WillPopScope
ویجت برای رهگیری رویداد دکمه برگشت استفاده می شود. هنگامی که دکمه بازگشت فشار داده می شود، انواع بارکد به عنوان یک شی JSON برگردانده می شود.
پیش نمایش دوربین و اسکن بارکد در زمان واقعی
پلاگین فلاتر Dynamsoft Barcode Reader به توسعه دهندگان کمک می کند تا عملکرد اسکن بارکد را با چند خط کد دارت در برنامه های Flutter خود ادغام کنند. این افزونه از تشخیص چند کد از یک تصویر واحد و جریان دوربین در زمان واقعی پشتیبانی می کند.
برای استفاده از دوربین iOS، باید توضیحات زیر را به دوربین اضافه کنید ios/Runner/Info.plist
قبل از نوشتن هر کدی فایل کنید.
<key>NSCameraUsageDescription</key>
<string>Can I use the camera please?</string>
<key>NSMicrophoneUsageDescription</key>
<string>Can I use the mic please?</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Load document images from gallery</string>
پلاگین اسکنر بارکد Flutter را می توان به صورت زیر استفاده کرد:
-
SDK را راه اندازی کنید.
final DCVCameraView _cameraView = DCVCameraView(); late final DCVCameraEnhancer _cameraEnhancer; late final DCVBarcodeReader _barcodeReader; late ScanProvider _scanProvider; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); _sdkInit(); } Future<void> _sdkInit() async { _scanProvider = Provider.of<ScanProvider>(context, listen: false); _barcodeReader = await DCVBarcodeReader.createInstance(); _cameraEnhancer = await DCVCameraEnhancer.createInstance(); DBRRuntimeSettings currentSettings = await _barcodeReader.getRuntimeSettings(); if (_scanProvider.types != 0) { currentSettings.barcodeFormatIds = _scanProvider.types; } else { currentSettings.barcodeFormatIds = EnumBarcodeFormat.BF_ALL; } currentSettings.expectedBarcodeCount = 0; await _barcodeReader .updateRuntimeSettingsFromTemplate(EnumDBRPresetTemplate.DEFAULT); await _barcodeReader.updateRuntimeSettings(currentSettings); _cameraView.overlayVisible = true; _cameraView.torchButton = TorchButton( visible: true, ); await _barcodeReader.enableResultVerification(true); _barcodeReader.receiveResultStream().listen((List<BarcodeResult>? res) { if (mounted) { decodeRes = res ?? []; String msg = ''; for (var i = 0; i < decodeRes.length; i++) { msg += '${decodeRes[i].barcodeText}\n'; if (_scanProvider.results.containsKey(decodeRes[i].barcodeText)) { continue; } else { _scanProvider.results[decodeRes[i].barcodeText] = decodeRes[i]; } } setState(() {}); } }); start(); }
پردازش تصویر و رمزگشایی بارکد در کد اصلی انجام می شود. بنابراین، عملکرد بهتر از برخی از افزونههایی است که دادههای تصویر را برای پردازش به کد Dart برمیگردانند. با گوش دادن به آن به راحتی می توانید نتایج بارکد را دریافت کنید
receiveResultStream()
. -
دوربین را روشن و متوقف کنید.
Future<void> stop() async { await _cameraEnhancer.close(); await _barcodeReader.stopScanning(); } Future<void> start() async { _isCameraReady = true; setState(() {}); Future.delayed(const Duration(milliseconds: 100), () async { _cameraView.overlayVisible = true; await _barcodeReader.startScanning(); await _cameraEnhancer.open(); }); }
را
Future.delayed()
برای تضمین آماده بودن ویجت نمای دوربین قبل از شروع اسکن بارکد استفاده می شود. -
طرحی را ایجاد کنید که شامل نمای دوربین و نمای نتیجه باشد.
Widget createSwitchWidget(bool switchValue) { if (!_isCameraReady) { // Return loading indicator if camera is not ready yet. return const Center( child: CircularProgressIndicator(), ); } if (switchValue) { return Stack( children: [ Container( color: Colors.white, ), Container( height: MediaQuery.of(context).size.height - 200 - MediaQuery.of(context).padding.top, color: Colors.white, child: Center( child: createListView(context), ), ), if (_isScanning) Positioned( top: 0, right: 20, child: SizedBox( width: 160, height: 160, child: _cameraView, ), ), Positioned( bottom: 50, left: 50, right: 50, child: SizedBox( width: MediaQuery.of(context).size.width * 0.5, height: 64, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ ElevatedButton( onPressed: () { if (_isScanning) { _isScanning = false; stop(); _scanButtonText = 'Start Scanning'; setState(() {}); } else { _isScanning = true; _scanButtonText = 'Stop Scanning'; start(); } }, child: Text(_scanButtonText), ), Center( child: IconButton( icon: const Icon(Icons.flash_on), onPressed: () { if (_isFlashOn) { _isFlashOn = false; _cameraEnhancer.turnOffTorch(); } else { _isFlashOn = true; _cameraEnhancer.turnOnTorch(); } }, ), ), ], )), ), ], ); } else { return Stack( children: [ Container( child: _cameraView, ), SizedBox( height: 100, child: ListView.builder( itemBuilder: listItem, itemCount: decodeRes.length, ), ), Positioned( bottom: 50, left: 50, right: 50, child: SizedBox( width: 64, height: 64, child: ElevatedButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => const HistoryView( title: 'Scan Results', )), ); }, child: const Text('Show Results'), ), )) ], ); } }
به طور پیش فرض، نمای دوربین پر از صفحه است. با فشار دادن دکمه سوئیچ واقع در گوشه سمت راست بالا، اندازه نمای دوربین به یک پنجره کوچکتر تغییر می کند و روی نمای نتیجه قرار می گیرد. نمای نتیجه یک نمای لیست است که نتایج بارکد را نمایش می دهد.
بارکد، کد QR و DataMatrix را از Image Files بخوانید
را image_picker
افزونه به شما امکان می دهد یک تصویر را از گالری انتخاب کنید یا با دوربین عکس بگیرید. این قطعه کد است:
onPressed: () async {
XFile? pickedFile =
await _imagePicker.pickImage(source: ImageSource.gallery);
XFile? pickedFile =
await _imagePicker.pickImage(source: ImageSource.camera);
},
پس از انتخاب یک تصویر، باید از آن استفاده کنید FlutterExifRotation.rotateImage
برای چرخاندن تصویر به جهت صحیح. در غیر این صورت، مختصات بارکد ممکن است نادرست باشد.
if (pickedFile != null) {
final rotatedImage = await FlutterExifRotation.rotateImage(
path: pickedFile.path);
_file = rotatedImage.path;
_results = await _barcodeReader.decodeFile(_file!) ?? [];
for (var i = 0; i < _results.length; i++) {
if (_scanProvider.results
.containsKey(_results[i].barcodeText)) {
continue;
} else {
_scanProvider.results[_results[i].barcodeText] =
_results[i];
}
}
}
را decodeFile()
روش برای رمزگشایی بارکد از فایل تصویر استفاده می شود. نتیجه لیستی از BarcodeResult
اشیاء. می توانید استفاده کنید barcodeText
دارایی برای بدست آوردن مقدار بارکد
نمایش نتیجه
نمای نتیجه یک نمای لیست است که نتایج بارکد را نمایش می دهد. را ListView.builder
برای ایجاد نمای لیست استفاده می شود.
Widget createListView(BuildContext context) {
ScanProvider scanProvider = Provider.of<ScanProvider>(context);
return ListView.builder(
itemCount: scanProvider.results.length,
itemBuilder: (context, index) {
return ListTile(
title: createURLString(
scanProvider.results.values.elementAt(index).barcodeText),
subtitle: Text(
scanProvider.results.values.elementAt(index).barcodeFormatString),
);
});
}
اگر نتیجه یک URL معتبر HTTP یا HTTPS است، می توانید از آن استفاده کنید launchUrlString()
عملکرد برای باز کردن آن علاوه بر این، میتوانید نظارت بر رویداد با فشار طولانی را در مورد فهرست فعال کنید تا گزینه اشتراکگذاری نتیجه بارکد را در اختیار کاربران قرار دهید.
Widget createURLString(String text) {
// Create a regular expression to match URL strings.
RegExp urlRegExp = RegExp(
r'^(https?|http)://[^\s/$.?#].[^\s]*$',
caseSensitive: false,
multiLine: false,
);
if (urlRegExp.hasMatch(text)) {
return InkWell(
onLongPress: () {
Share.share(text, subject: 'Scan Result');
},
child: Text(
text,
style: const TextStyle(color: Colors.blue),
),
onTap: () async {
launchUrlString(text);
},
);
} else {
return InkWell(
onLongPress: () async {
Share.share(text, subject: 'Scan Result');
},
child: Text(text),
);
}
}
اسکنر چند کد را در اندروید و iOS اجرا کنید
flutter run
کد منبع
https://github.com/yushulx/multiple-barcode-qrcode-datamatrix-scan