import 'dart:async'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; import 'package:jc_printer/jc_printer.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( home: HomePage(), ); } } class HomePage extends StatefulWidget { const HomePage({super.key}); @override State createState() => _HomePageState(); } class _HomePageState extends State { final TextEditingController _labelWidthInput = TextEditingController(); final TextEditingController _labelHeightInput = TextEditingController(); final TextEditingController _countInput = TextEditingController(); final _printer = JcPrinter(); ConnectState _connectState = ConnectState.none; StreamSubscription? _connectStateSubs; StreamSubscription? _printingCountSubs; StreamSubscription>? _errorInfoSubs; DiscoveredDevice? _device; String get _title { switch (_connectState) { case ConnectState.connecting: return '连接中'; case ConnectState.connected: return _device?.name ?? '已连接'; case ConnectState.none: return '未连接'; } } @override void initState() { _labelWidthInput.text = '40'; _labelHeightInput.text = '30'; _countInput.text = '1'; _connectStateSubs = _printer.connectStateStream.listen( _connectStateListener, ); _printingCountSubs = _printer.printingCountStream.listen( _printingCountListener, ); _errorInfoSubs = _printer.errorInfoStream.listen( _errorInfoListener, ); super.initState(); } @override void dispose() { _labelWidthInput.dispose(); _labelHeightInput.dispose(); _countInput.dispose(); _connectStateSubs?.cancel(); _printingCountSubs?.cancel(); _errorInfoSubs?.cancel(); super.dispose(); } void _connectStateListener(ConnectState state) { setState(() { _connectState = state; }); } void _printingCountListener(int count) { print(count); } void _errorInfoListener(Map error) { debugPrint(error.toString()); } void _connect() { _printer.connect(_device!.name); } void _startPrint() async { final count = int.tryParse(_countInput.value.text) ?? 0; _printer.setTotalPrints(count); await _printer.startPrint(); final data = await _getLabelData(); await _printer.commit(data: data, count: count); } Future _getLabelData() async { final labelWidth = double.tryParse(_labelWidthInput.value.text) ?? 0; final labelHeight = double.tryParse(_labelHeightInput.value.text) ?? 0; await _printer.initDrawingBoard( width: labelWidth, height: labelHeight, font: 'SourceHanSans-Regular.ttc', ); await _printer.drawLabelText( width: labelWidth, height: 7, content: '打印测试', fontSize: 7, ); await _printer.drawLabelBarcode( width: 30, x: 5, y: 7, height: 18, text: '123456', fontSize: 4, textHeight: 4, ); return _printer.getLabelData(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: _connectState == ConnectState.connecting ? const CupertinoActivityIndicator() : Text(_title), actions: [ TextButton( onPressed: () async { if (_connectState == ConnectState.connected) { _printer.disconnect(); return; } final result = await showDialog( context: context, builder: (BuildContext context) => _DevicesDialog( onTap: Navigator.of(context).pop, ), ); if (result == null) return; _device = result; _connect(); }, child: Text( _connectState == ConnectState.connected ? '断开' : '连接设备', style: const TextStyle(color: Colors.white), ), ), ], ), body: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Center( child: Column( children: [ TextField( controller: _labelWidthInput, decoration: const InputDecoration(label: Text('标签宽度')), ), TextField( controller: _labelHeightInput, decoration: const InputDecoration(label: Text('标签高度')), ), TextField( controller: _countInput, decoration: const InputDecoration(label: Text('每份数量')), ), const SizedBox(height: 20), ElevatedButton( onPressed: _startPrint, child: const Text('开始打印'), ), ], ), ), ), ); } } class _DevicesDialog extends StatefulWidget { final void Function(DiscoveredDevice device)? onTap; const _DevicesDialog({ Key? key, this.onTap, }) : super(key: key); @override State<_DevicesDialog> createState() => _DevicesDialogState(); } class _DevicesDialogState extends State<_DevicesDialog> { final _ble = FlutterReactiveBle(); final List _devices = []; StreamSubscription? _scanSubs; @override void initState() { _scanSubs = _ble.scanForDevices( withServices: [], ).listen(_scanListener); super.initState(); } @override void dispose() { _scanSubs?.cancel(); super.dispose(); } void _scanListener(DiscoveredDevice device) { if (device.name.isEmpty) return; if (device.connectable != Connectable.available) return; final index = _devices.indexWhere( (element) => element.id == device.id, ); if (index > -1) { _devices[index] = device; } else { _devices.add(device); } if (mounted) setState(() {}); } @override Widget build(BuildContext context) { return Dialog( child: ConstrainedBox( constraints: const BoxConstraints(maxHeight: 400), child: ListView.separated( itemBuilder: (BuildContext context, int index) { final item = _devices[index]; return ListTile( title: Text(item.name), onTap: () => widget.onTap?.call(item), ); }, itemCount: _devices.length, separatorBuilder: (_, __) => const Divider(), ), ), ); } }