Вырезанный текстовый эффект во флаттере - PullRequest
0 голосов
/ 03 сентября 2018

Как я могу сделать текст, вырезанный в контейнер, который оставляет содержимое под ним видимым?

Вот именно то, что я имею в виду:

Как видите изображение видно под текстом . Как я мог это сделать?

Ответы [ 2 ]

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

Для этого вы можете использовать ShaderMask , который позволяет применять шейдер к виджету, принимая во внимание Blend Mode . Нас интересует Blend Mode, поэтому шейдер будет простым цветом:

class Cutout extends StatelessWidget {
  const Cutout({
    Key key,
    @required this.color,
    @required this.child,
  }) : super(key: key);

  final Color color;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return ShaderMask(
      blendMode: BlendMode.srcOut,
      shaderCallback: (bounds) => LinearGradient(colors: [color], stops: [0.0]).createShader(bounds),
      child: child,
    );
  }
}

Вот пример рендера: Render of the Cutout widget

Для вашего точного примера изображения дочерним элементом должен быть виджет Text, и вы также должны включить его в ClipRRect для закругленных углов (или вы можете найти более оптимальные решения, используя BoxDecoration, если влияние на производительность из ClipRRect это проблема)

Преимущество этого решения в том, что оно работает с любым виджетом в качестве дочернего элемента и является составным виджетом, который можно вставлять в макет.

0 голосов
/ 03 сентября 2018

Вы должны использовать CustomPainter, TextPainter, BlendMode и saveLayer:

result

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Playground',
      home: TestPage(),
    );
  }
}

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        image: DecorationImage(image: AssetImage('assets/earth.jpg'), fit: BoxFit.cover),
      ),
      child: Center(
        child: CustomPaint(
          painter: CutOutTextPainter(text: 'YOUR NAME'),
        ),
      ),
    );
  }
}

class CutOutTextPainter extends CustomPainter {
  CutOutTextPainter({this.text}) {
    _textPainter = TextPainter(
      text: TextSpan(
        text: text,
        style: TextStyle(
          fontSize: 40.0,
          fontWeight: FontWeight.w600,
        ),
      ),
      textDirection: TextDirection.ltr,
    );
    _textPainter.layout();
  }

  final String text;
  TextPainter _textPainter;

  @override
  void paint(Canvas canvas, Size size) {
    // Draw the text in the middle of the canvas
    final textOffset = size.center(Offset.zero) - _textPainter.size.center(Offset.zero);
    final textRect = textOffset & _textPainter.size;

    // The box surrounding the text should be 10 pixels larger, with 4 pixels corner radius
    final boxRect = RRect.fromRectAndRadius(textRect.inflate(10.0), Radius.circular(4.0));
    final boxPaint = Paint()..color = Colors.white..blendMode=BlendMode.srcOut;

    canvas.saveLayer(boxRect.outerRect, Paint());

    _textPainter.paint(canvas, textOffset);
    canvas.drawRRect(boxRect, boxPaint);

    canvas.restore();
  }

  @override
  bool shouldRepaint(CutOutTextPainter oldDelegate) {
    return text != oldDelegate.text;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...