برنامه نویسی

ساخت چندین بارکد، کد 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 ویجت برای اشتراک گذاری وضعیت جهانی:

  1. ایجاد یک 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();
      }
    }
    
    
  2. ایجاد یک ChangeNotifierProvider ویجت برای بسته بندی ScanProvider ویجت، و سپس اضافه کنید ScanProvider ویجت به MultiProvider ویجت را MultiProvider ویجت می تواند شامل چندین مورد باشد ChangeNotifierProvider ویجت ها

    void main() {
      runApp(MultiProvider(providers: [
        ChangeNotifierProvider(create: (_) => SwitchProvider()),
        ChangeNotifierProvider(create: (_) => ScanProvider()),
      ], child: const MyApp()));
    }
    

    را SwitchProvider ویجت برای تغییر اندازه دوربین در بخش بعدی استفاده خواهد شد.

  3. ذخیره انواع بارکد در 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 را می توان به صورت زیر استفاده کرد:

  1. 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().

  2. دوربین را روشن و متوقف کنید.

    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() برای تضمین آماده بودن ویجت نمای دوربین قبل از شروع اسکن بارکد استفاده می شود.

  3. طرحی را ایجاد کنید که شامل نمای دوربین و نمای نتیجه باشد.

    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 بخوانید

کد qr را از یک فایل تصویری بخوانید

را 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

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا