Показать замаскированную область поверх виджета камеры - PullRequest
0 голосов
/ 08 апреля 2019

Я пытаюсь реализовать устройство для считывания кредитных карт (используя какой-то API).Чтобы пользователь мог сфотографировать карту, я представляю виджет предварительного просмотра камеры в полноэкранном режиме.Я хотел бы замаскировать область, чтобы пользователь центрировал карту там.

Он является иллюстрацией того, что я имею в виду

Мне было интересно, как этомаскировка может быть выполнена в флаттер?В настоящее время я просто рисую BoxDecoration, но в нем отсутствует полупрозрачная, затененная область.

Container(
width: MediaQuery.of(context).size.width * 0.8,
height: MediaQuery.of(context).size.width * 0.8 / 1.55,
decoration: new BoxDecoration(
    border: Border.all(
        color: Colors.white,
        width: 2.0,
        style: BorderStyle.solid),
    shape: BoxShape.rectangle,
    borderRadius: BorderRadius.all(Radius.circular(4.0))),
)

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

Теперь я просто выбрал собственный BoxPainter и сначала нарисовал фон, затем область карты и, наконец, смешал слои, чтобы «вырезать» центральную часть.

import 'package:flutter/widgets.dart';

class CardDecoration extends Decoration {
  @override
  BoxPainter createBoxPainter([VoidCallback onChanged]) {
    return _CardPainter();
  }
}

class _CardPainter extends BoxPainter {
  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    final clearPaint = new Paint()
    ..color = Colors.black
    ..style = PaintingStyle.fill
    ..blendMode = BlendMode.dstOut;

    final bgPaint = new Paint()
      ..color = Color.fromARGB(150, 0, 0, 0)
      ..style = PaintingStyle.fill;

    final borderPaint = new Paint()
    ..color = Colors.white.withAlpha(120)
    ..style = PaintingStyle.stroke
    ..strokeWidth = 3.0;

    final rect = offset & configuration.size;
    final cardWidth = 0.8*rect.width;
    final cardHeight = cardWidth/1.55;

    canvas.saveLayer(Rect.fromLTRB(0, 0, rect.width, rect.height), clearPaint);

    canvas.drawPaint(bgPaint);

    canvas.saveLayer(Rect.fromLTRB(0, 0, rect.width, rect.height), clearPaint);
    canvas.drawRRect(RRect.fromLTRBR(0.1*rect.width, (rect.height-cardHeight)/2, 0.9*rect.width, (rect.height+cardHeight)/2, Radius.circular(8)), bgPaint);
    canvas.restore();
    canvas.restore();
    canvas.drawRRect(RRect.fromLTRBR(0.1*rect.width, (rect.height-cardHeight)/2, 0.9*rect.width, (rect.height+cardHeight)/2, Radius.circular(8)), borderPaint);
  }
}
0 голосов
/ 08 апреля 2019

Вы можете попробовать что-то подобное на данный момент, но это очень неэффективное решение, и я уверен, что должно быть лучшее решение, которое я тоже хотел бы знать.

 @override
  Widget build(BuildContext context) {
    if (!controller.value.isInitialized) {
      return Container();
    }
    return Container(
      height: MediaQuery.of(context).size.height,
      child: Stack(
        children: <Widget>[
          CustomPaint(
            foregroundPainter: P(),
            child: CameraPreview(controller),
          ),
          ClipPath(
            clipper: Clip(),
            child: CameraPreview(controller)),
        ],
      ),
    );
  }
class P extends CustomPainter{
  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawColor(Colors.grey.withOpacity(0.8), BlendMode.dstOut);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return true;
  }

}
class Clip extends CustomClipper<Path>{
  @override
  getClip(Size size) {
    print(size);
    Path path = Path()
    ..addRRect(RRect.fromRectAndRadius(Rect.fromLTWH(10, size.height/2-120, size.width-20, 240), Radius.circular(26)));
    return path;
  }

  @override
  bool shouldReclip(oldClipper) {
    // TODO: implement shouldReclip
    return true;
  }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...