zpl_plugin_package 0.0.8
zpl_plugin_package: ^0.0.8 copied to clipboard
A Flutter plugin for Zebra ZPL printers. Supports WiFi connection, text, barcode, image and PDF printing, raw ZPL commands, and real-time connection monitoring. Android only.
import 'package:flutter/material.dart';
import 'package:zpl_plugin_package/flutter_zebra_plugin.dart';
void main() {
runApp(const ZebraExampleApp());
}
class ZebraExampleApp extends StatelessWidget {
const ZebraExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Zebra ZPL Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
useMaterial3: true,
),
home: const PrinterDemoPage(),
);
}
}
class PrinterDemoPage extends StatefulWidget {
const PrinterDemoPage({super.key});
@override
State<PrinterDemoPage> createState() => _PrinterDemoPageState();
}
class _PrinterDemoPageState extends State<PrinterDemoPage> {
final FlutterZebraIntegration _zebra = FlutterZebraIntegration();
final _ipController = TextEditingController(text: '192.168.1.100');
final _portController = TextEditingController(text: '9100');
final _textController = TextEditingController(text: 'Hello, Zebra!');
final _barcodeController = TextEditingController(text: '123456789012');
final _zplController =
TextEditingController(text: '^XA^FO50,50^A0N,50,50^FDHello^FS^XZ');
String _statusMessage = 'Not connected';
bool _isLoading = false;
@override
void dispose() {
_zebra.dispose();
_ipController.dispose();
_portController.dispose();
_textController.dispose();
_barcodeController.dispose();
_zplController.dispose();
super.dispose();
}
Future<void> _run(Future<void> Function() action) async {
setState(() => _isLoading = true);
try {
await action();
} catch (e) {
_setStatus('Error: $e');
} finally {
if (mounted) setState(() => _isLoading = false);
}
}
void _setStatus(String msg) {
if (mounted) setState(() => _statusMessage = msg);
}
Future<void> _connect() => _run(() async {
final ok = await _zebra.connectToPrinter(
_ipController.text.trim(),
_portController.text.trim(),
);
_setStatus(ok == true ? 'Connected' : 'Connection refused');
});
Future<void> _disconnect() => _run(() async {
await _zebra.disconnectPrinter();
_setStatus('Disconnected');
});
Future<void> _printText() => _run(() async {
final result = await _zebra.printText(
_textController.text,
x: '10',
y: '20',
size: 3,
);
_setStatus(result ?? 'Done');
});
Future<void> _printBarcode() => _run(() async {
final result = await _zebra.printBarcode(
_barcodeController.text,
type: 4,
height: '100',
);
_setStatus(result ?? 'Done');
});
Future<void> _sendZpl() => _run(() async {
final result = await _zebra.sendZPLCommand(_zplController.text);
_setStatus(result ?? 'Done');
});
@override
Widget build(BuildContext context) {
final connected = _zebra.isPrinterConnected;
return Scaffold(
appBar: AppBar(
title: const Text('Zebra ZPL Printer Demo'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: _isLoading
? const Center(child: CircularProgressIndicator())
: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_StatusBanner(
message: _statusMessage, connected: connected),
const SizedBox(height: 16),
// ── Connection ─────────────────────────────────────────
_SectionCard(
title: 'Connection',
children: [
_LabeledField(
label: 'Printer IP',
controller: _ipController,
hint: '192.168.1.100',
),
const SizedBox(height: 8),
_LabeledField(
label: 'Port',
controller: _portController,
hint: '9100',
keyboardType: TextInputType.number,
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: FilledButton.icon(
onPressed: connected ? null : _connect,
icon: const Icon(Icons.wifi),
label: const Text('Connect'),
),
),
const SizedBox(width: 8),
Expanded(
child: OutlinedButton.icon(
onPressed: connected ? _disconnect : null,
icon: const Icon(Icons.wifi_off),
label: const Text('Disconnect'),
),
),
],
),
],
),
// ── Print Text ─────────────────────────────────────────
_SectionCard(
title: 'Print Text',
children: [
_LabeledField(
label: 'Text',
controller: _textController,
hint: 'Hello, Zebra!',
),
const SizedBox(height: 12),
FilledButton.icon(
onPressed: _printText,
icon: const Icon(Icons.text_fields),
label: const Text('Print Text'),
),
],
),
// ── Print Barcode ──────────────────────────────────────
_SectionCard(
title: 'Print Barcode (Code 128)',
children: [
_LabeledField(
label: 'Data',
controller: _barcodeController,
hint: '123456789012',
keyboardType: TextInputType.number,
),
const SizedBox(height: 12),
FilledButton.icon(
onPressed: _printBarcode,
icon: const Icon(Icons.qr_code),
label: const Text('Print Barcode'),
),
],
),
// ── Raw ZPL ────────────────────────────────────────────
_SectionCard(
title: 'Send Raw ZPL Command',
children: [
_LabeledField(
label: 'ZPL',
controller: _zplController,
hint: '^XA…^XZ',
maxLines: 3,
),
const SizedBox(height: 12),
FilledButton.icon(
onPressed: _sendZpl,
icon: const Icon(Icons.terminal),
label: const Text('Send ZPL'),
),
],
),
],
),
),
);
}
}
// ── Shared widgets ──────────────────────────────────────────────────────────
class _StatusBanner extends StatelessWidget {
const _StatusBanner({required this.message, required this.connected});
final String message;
final bool connected;
@override
Widget build(BuildContext context) {
final color = connected ? Colors.green : Colors.orange;
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: color.shade50,
border: Border.all(color: color),
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Icon(
connected ? Icons.check_circle : Icons.info_outline,
color: color,
),
const SizedBox(width: 8),
Expanded(
child: Text(
message,
style: TextStyle(color: color.shade800),
),
),
],
),
);
}
}
class _SectionCard extends StatelessWidget {
const _SectionCard({required this.title, required this.children});
final String title;
final List<Widget> children;
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.only(top: 16),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
title,
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
...children,
],
),
),
);
}
}
class _LabeledField extends StatelessWidget {
const _LabeledField({
required this.label,
required this.controller,
required this.hint,
this.keyboardType,
this.maxLines = 1,
});
final String label;
final TextEditingController controller;
final String hint;
final TextInputType? keyboardType;
final int maxLines;
@override
Widget build(BuildContext context) {
return TextField(
controller: controller,
keyboardType: keyboardType,
maxLines: maxLines,
decoration: InputDecoration(
labelText: label,
hintText: hint,
border: const OutlineInputBorder(),
isDense: true,
),
);
}
}