xue_hua_qr_code
Out-of-the-box QR code widget for Flutter. Pure Dart — no native dependencies, no platform channels.
XueHuaQrCode(value: 'https://example.com')
That is all you need: a scannable black-on-white QR code that adapts to its parent constraints.
Features
- One required parameter — pass
value, get a standard QR code with sensible defaults - Styling — square / circle / rounded modules, colors, gradients, proportional corner radius and gaps
- Center logo —
ImageProviderbased, sized as a fraction of the QR content side, identical in widget and export - Automatic mask selection — the best of 8 mask patterns is chosen per ISO/IEC 18004 penalty rules
- Robust error handling — empty / oversized content falls back to
errorBuilderon the widget; a failing logo (e.g. network error) degrades to a plain, still-scannable QR code - Export —
XueHuaQrCode.toImage()andXueHuaQrCode.toPngBytes()share the exact painter used on screen - AI agent skills — official Agent Skills ship in the package for Cursor, Claude Code, and other agents
Installation
dependencies:
xue_hua_qr_code: ^2.0.2
Basic usage
import 'package:xue_hua_qr_code/xue_hua_qr_code.dart';
// Adapts to the parent's shortest bounded side.
XueHuaQrCode(value: 'https://example.com')
// Fixed size.
XueHuaQrCode(value: 'https://example.com', size: 240)
Advanced usage
Custom style
XueHuaQrCode(
value: 'https://example.com',
size: 240,
style: const QrStyle(
shape: QrModuleShape.roundedSquare,
moduleRadius: 0.4, // fraction of a module, 0~0.5
moduleGap: 0.15, // fraction of a module, 0~0.5
gradient: LinearGradient(colors: [Colors.pink, Colors.blue]),
padding: EdgeInsets.all(12), // quiet zone
),
)
With a logo
XueHuaQrCode(
value: 'https://example.com',
size: 240,
style: const QrStyle(shape: QrModuleShape.roundedSquare),
logo: const QrLogo(
image: AssetImage('assets/logo.png'), // NetworkImage / MemoryImage also work
scale: 0.22, // fraction of the QR content side, (0, 0.35]
padding: 6,
borderRadius: 8,
),
// Error correction is automatically raised to `high` when a logo is present.
)
If the logo fails to load (missing asset, network error), the widget renders the full QR code without the logo — it never leaves an unscannable hole.
Error handling
XueHuaQrCode(
value: userInput, // may be empty or too long
errorBuilder: (context, error, stackTrace) => const Icon(Icons.error),
)
The widget catches encoding failures. toImage / toPngBytes rethrow them (ArgumentError for empty value, InsufficientInformationDensityException when the payload exceeds version 40).
Export
// PNG bytes — save to a file or show with Image.memory.
// `size` defaults to 512; encoding failures throw (unlike the widget).
final bytes = await XueHuaQrCode.toPngBytes(
'https://example.com',
size: 512,
style: const QrStyle(shape: QrModuleShape.circle),
);
// dart:ui Image. Dispose the image when you are done with it.
final image = await XueHuaQrCode.toImage('https://example.com', size: 512);
API reference
XueHuaQrCode
| Parameter | Type | Default | Description |
|---|---|---|---|
value |
String |
required | Content to encode |
size |
double? |
null |
Fixed logical side; null uses the parent's shortest finite constraint |
style |
QrStyle |
QrStyle() |
Visual style |
logo |
QrLogo? |
null |
Center logo |
errorCorrectionLevel |
QrErrorLevel? |
null |
Automatic via effectiveErrorLevel: medium without a logo, high with one |
errorBuilder |
ImageErrorWidgetBuilder? |
null |
Fallback UI when encoding fails; debug placeholder / release blank if omitted |
semanticsLabel |
String? |
null |
Accessibility label; null is shown as 'QR code' |
QrErrorLevel get effectiveErrorLevel — errorCorrectionLevel if set, otherwise high when logo != null and medium otherwise.
QrStyle
| Parameter | Type | Default | Description |
|---|---|---|---|
shape |
QrModuleShape |
square |
square / circle / roundedSquare |
color |
Color |
Color(0xFF000000) |
Foreground color (ignored when gradient is set) |
backgroundColor |
Color |
Color(0xFFFFFFFF) |
Background; pass Colors.transparent explicitly if needed |
gradient |
Gradient? |
null |
Foreground gradient (any Flutter Gradient) |
moduleRadius |
double? |
per shape | Corner radius as a fraction of module size, 0~0.5 |
moduleGap |
double? |
per shape | Gap between modules as a fraction of module size, 0~0.5 |
padding |
EdgeInsets |
EdgeInsets.all(8) |
Quiet zone around the code (logical px); applied to widget and export |
When moduleRadius / moduleGap are null, effectiveModuleRadius / effectiveModuleGap resolve by shape: square → 0.0 / 0.0, circle → 0.5 / 0.1, roundedSquare → 0.3 / 0.1.
copyWith uses ?? and cannot clear gradient back to null; construct a new QrStyle to drop a gradient.
QrLogo
| Parameter | Type | Default | Description |
|---|---|---|---|
image |
ImageProvider |
required | Logo image |
scale |
double |
0.2 |
Logo side as a fraction of the QR content side, (0, 0.35] |
padding |
double |
4 |
Backdrop padding around the logo (logical px) |
backgroundColor |
Color? |
null |
Backdrop color; null uses style.backgroundColor |
borderRadius |
double |
0 |
Backdrop corner radius (logical px) |
QrErrorLevel
low (~7%), medium (~15%), quartile (~25%), high (~30%) — the approximate share of data that can be recovered.
Public fields value (format-information BCH: L=1, M=0, Q=3, H=2) and maxTypeNum (encoder version-search bound) are for the encoder. Pass the enum names from app code.
Export
| Method | Returns | Description |
|---|---|---|
XueHuaQrCode.toImage(value, {size = 512, style, logo, errorCorrectionLevel}) |
Future<ui.Image> |
Render to a dart:ui image |
XueHuaQrCode.toPngBytes(value, {size = 512, style, logo, errorCorrectionLevel}) |
Future<Uint8List> |
Render to PNG bytes |
Both use the same painter as the widget. Encoding failures throw; a failed logo load degrades to a full QR without a logo. size must be > 0. Dispose the ui.Image from toImage when finished. toPngBytes may throw StateError if PNG encoding fails.
QrMatrix
Immutable encode result. Create with QrMatrix.encode(value, {errorLevel = QrErrorLevel.medium}).
| Member | Type | Description |
|---|---|---|
value |
String |
Encoded payload |
errorLevel |
QrErrorLevel |
Level used for this encode |
version |
int |
QR version 1–40 |
moduleCount |
int |
Modules per side (version * 4 + 17) |
alignmentCenters |
List<(int, int)> |
Alignment-pattern centers (row, col) |
finderOrigins |
List<(int, int)> |
Top-left corners of the three 7×7 finders |
isDark(row, col) |
bool |
Whether that module is dark |
isInFinderPattern(row, col) |
bool |
Inside a 7×7 finder |
isInAlignmentPattern(row, col) |
bool |
Inside a 5×5 alignment pattern |
Empty value throws ArgumentError. Over-capacity throws InsufficientInformationDensityException. Equality compares value and errorLevel only.
QrPainter
CustomPainter shared by the widget and export.
const QrPainter({
required QrMatrix matrix,
QrStyle style = const QrStyle(),
QrLogo? logo,
ui.Image? logoImage,
})
paint / shouldRepaint follow CustomPainter. A logo is drawn only when both logo and logoImage are non-null; otherwise the full matrix is painted (no hole).
InsufficientInformationDensityException
Thrown when the payload does not fit QR version 40 at the chosen error level. Optional message includes needed vs maximum bits. toString() is InsufficientInformationDensityException: ${message ?? ''}.
There is no public version override: QrMatrix.encode always selects the smallest fitting version.
AI agent skills
This package ships Agent Skills that teach AI coding assistants the public API. After adding the dependency, install them with:
dart run skills@ get
That scans your dependencies and copies selected skills into your agent's skills directory (for example .agents/skills/ or .cursor/skills/). Re-run after upgrading the package.
| Skill | Use it for |
|---|---|
xue-hua-qr-code-widget |
XueHuaQrCode, QrErrorLevel, errorBuilder, toImage / toPngBytes |
xue-hua-qr-code-styling |
QrStyle, QrModuleShape, QrLogo |
xue-hua-qr-code-painter |
QrMatrix, QrPainter, custom CustomPaint |
Each skill includes a references/ file with every public constructor, field, getter, and method. Agents that load skills from another directory can copy the folders under skills/ in this repository.
Example app
cd example
flutter run
Five tabs demonstrate basic, circle, rounded, gradient, and logo styles, plus PNG export.
License
MIT — encoding internals ported from qrcode-kotlin.
Libraries
- xue_hua_qr_code
- 开箱即用的 Flutter 二维码组件。