264 lines
7.0 KiB
Dart
264 lines
7.0 KiB
Dart
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<HomePage> createState() => _HomePageState();
|
|
}
|
|
|
|
class _HomePageState extends State<HomePage> {
|
|
final TextEditingController _labelWidthInput = TextEditingController();
|
|
final TextEditingController _labelHeightInput = TextEditingController();
|
|
final TextEditingController _countInput = TextEditingController();
|
|
final TextEditingController _contentInput = TextEditingController();
|
|
final _printer = JcPrinter();
|
|
int _count = 0;
|
|
ConnectState _connectState = ConnectState.none;
|
|
StreamSubscription<ConnectState>? _connectStateSubs;
|
|
StreamSubscription<int>? _printingCountSubs;
|
|
StreamSubscription<Map<String, String>>? _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';
|
|
_contentInput.text = '歪脖子';
|
|
_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();
|
|
_contentInput.dispose();
|
|
_connectStateSubs?.cancel();
|
|
_printingCountSubs?.cancel();
|
|
_errorInfoSubs?.cancel();
|
|
super.dispose();
|
|
}
|
|
|
|
void _connectStateListener(ConnectState state) {
|
|
setState(() {
|
|
_connectState = state;
|
|
});
|
|
}
|
|
|
|
void _printingCountListener(int count) {
|
|
if (count == _count) _printer.endPrint();
|
|
}
|
|
|
|
void _errorInfoListener(Map<String, String> error) {
|
|
debugPrint(error.toString());
|
|
}
|
|
|
|
void _connect() {
|
|
_printer.connect(_device!.name);
|
|
}
|
|
|
|
void _startPrint() async {
|
|
final labelWidth = double.tryParse(_labelWidthInput.value.text) ?? 0;
|
|
final labelHeight = double.tryParse(_labelHeightInput.value.text) ?? 0;
|
|
_count = int.tryParse(_countInput.value.text) ?? 0;
|
|
final content = _contentInput.value.text.trim();
|
|
if (content.isEmpty || _count <= 0) return;
|
|
_printer.setTotalPrints(1);
|
|
await _printer.initDrawingBoard(
|
|
width: labelWidth,
|
|
height: labelHeight,
|
|
font: 'SourceHanSans-Regular.ttc',
|
|
);
|
|
await _printer.drawLabelText(
|
|
width: labelWidth,
|
|
height: 7,
|
|
content: content,
|
|
fontSize: 7,
|
|
);
|
|
await _printer.drawLabelBarcode(
|
|
width: 30,
|
|
x: 5,
|
|
y: 7,
|
|
height: 18,
|
|
text: '123456',
|
|
fontSize: 4,
|
|
textHeight: 4,
|
|
);
|
|
final data = await _printer.getLabelData();
|
|
_printer.startPrint(data: data, count: _count);
|
|
}
|
|
|
|
@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<DiscoveredDevice>(
|
|
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('打印数量')),
|
|
),
|
|
TextField(
|
|
controller: _contentInput,
|
|
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<DiscoveredDevice> _devices = [];
|
|
StreamSubscription<DiscoveredDevice>? _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(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|