答案 0 :(得分:1)
您必须使用CustomPainter
,TextPainter
,BlendMode
和saveLayer
:
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;
}
}
答案 1 :(得分:1)
您可以为此使用ShaderMask,这允许您将着色器应用于小部件,并考虑到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,
);
}
}
对于您的确切示例图片,该子项应为Text
小部件,并且还应将其包括在ClipRRect
中以用于圆角(或者您可以使用{{1 }}如果对BoxDecoration
的性能有影响)
此解决方案的优势在于,它可以与任何小部件一起使用,并且是一个可组合的小部件,可以在布局中弹出。