kevmoo / qr.dart

Dart QR code generation library.
https://pub.dev/packages/qr
BSD 3-Clause "New" or "Revised" License
352 stars 64 forks source link

[Proposal] Widget renders image instead of canvas #19

Closed apexJCL closed 5 years ago

apexJCL commented 5 years ago

I was working with a QR over a card that spins (Transform w/rotation) and could perceive that the performance was slow.

I ended up implementing a Widget that does kinda the same as the one included here but instead of using the CustomPainter, it uses a FutureBuilder that shows an indicator that fades when the image it's ready.

It could be something like:


class QrImage extends StatelessWidget {
  final String data;
  final int version;
  final int errorCorrectionLevel;
  final Color color;
  final Color backgroundColor;

  const QrImage({
    Key key,
    this.data,
    this.version = 4,
    this.errorCorrectionLevel = QrErrorCorrectLevel.M,
    this.color = Colors.black,
    this.backgroundColor = Colors.white,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final QrPainter _painter = QrPainter(
      data: data,
      version: version,
      errorCorrectionLevel: errorCorrectionLevel,
      color: color,
      gapless: true,
      emptyColor: backgroundColor,
    );

    return FutureBuilder<ByteData>(
      future: _painter.toImageData(512.0),
      builder: (BuildContext context, AsyncSnapshot<ByteData> snapshot) {
        return AnimatedCrossFade(
          firstChild: Container(
            alignment: Alignment.center,
          ),
          secondChild: Builder(builder: (BuildContext context) {
            if (snapshot.data == null || data == null) {
              return Center(
                child: Text('No se pudo cargar el token.'),
              );
            }

            return Image.memory(
              snapshot.data.buffer.asUint8List(),
              fit: BoxFit.contain,
            );
          }),
          crossFadeState: snapshot.connectionState == ConnectionState.done
              ? CrossFadeState.showSecond
              : CrossFadeState.showFirst,
          duration: const Duration(milliseconds: 250),
          layoutBuilder: (Widget topChild, Key topChildKey, Widget bottomChild,
              Key bottomChildKey) {
            return Stack(
              overflow: Overflow.visible,
              children: <Widget>[
                Positioned.fill(
                  key: bottomChildKey,
                  left: 0.0,
                  top: 0.0,
                  right: 0.0,
                  child: bottomChild,
                ),
                Positioned.fill(
                  key: topChildKey,
                  child: topChild,
                ),
              ],
            );
          },
        );
      },
    );
  }
}

The AnimatedCrossfade could be switched by anything else, but it can become useful to come bundled with the package, having different ways to render the Qr.

Feel free to dismiss this proposal if it doesn't suit the project and would be something rather mantained by the users instead of the package dev.

apexJCL commented 5 years ago

Oh, sorry, wrong repo