I need to make widget this widget. For this, I need to make text transparent on top of coloured container.
CodePudding user response:
You can use ShaderMask
with blendMode: BlendMode.srcOut,
And use it as a Child on Stack widget.
ClipRRect(
borderRadius: BorderRadius.circular(12),
child: ShaderMask(
blendMode: BlendMode.srcOut,
shaderCallback: (bounds) {
return LinearGradient(colors: [
Colors.white,
Colors.white,
]).createShader(bounds);
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"M",
style: TextStyle(
fontSize: 44,
),
),
),
),
)
CodePudding user response:
You can use ShaderMask
and Stack
to do this
Stack(
alignment: Alignment.center,
children: [
Container(
width: double.infinity,
height: 200,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('https://res.cloudinary.com/demo/image/upload/v1312461204/sample.jpg'),
fit: BoxFit.cover
)
),
),
ShaderMask(
blendMode: BlendMode.srcOut,
child: Padding(
padding: const EdgeInsets.fromLTRB(10, 20, 10, 20),
child: Text('M', style: TextStyle(fontSize: 30),),
),
shaderCallback: (bounds) =>
LinearGradient(colors: [Colors.white], stops: [0.0])
.createShader(bounds),
),
],
),
CodePudding user response:
Here is the method that perfectly worked for me:
class SoterRiskWidget extends StatelessWidget {
final String letter;
final double fontSize;
final Color color;
final double radius;
const SoterRiskWidget({
required this.letter,
required this.fontSize,
this.radius = 2,
this.color = Colors.white,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox.square(
dimension: fontSize,
child: CustomPaint(
painter: _CutOutTextPainter(
text: letter,
fontSize: fontSize,
fontWeight: FontWeight.w500,
color: color,
radius: radius,
),
),
);
}
}
class _CutOutTextPainter extends CustomPainter {
final String text;
final double fontSize;
final FontWeight fontWeight;
final Color color;
final double radius;
late final TextPainter _textPainter;
_CutOutTextPainter({
required this.text,
required this.fontSize,
required this.fontWeight,
required this.color,
required this.radius,
}) {
_textPainter = TextPainter(
text: TextSpan(
text: text,
style: TextStyle(
fontSize: fontSize,
fontWeight: fontWeight,
),
),
textDirection: TextDirection.ltr,
);
_textPainter.layout();
}
@override
void paint(Canvas canvas, Size size) {
Offset textOffset = size.center(Offset.zero) - _textPainter.size.center(Offset.zero);
final textRect = textOffset & _textPainter.size;
Rect newRect;
double dif = ((textRect.width - textRect.height).abs()) / 2.0;
if (textRect.width > textRect.height) {
newRect = Rect.fromLTRB(
textRect.left,
textRect.top - dif,
textRect.right,
textRect.bottom dif,
);
} else {
newRect = Rect.fromLTRB(
textRect.left - dif,
textRect.top,
textRect.right dif,
textRect.bottom,
);
}
final boxRect = RRect.fromRectAndRadius(newRect.inflate(0), Radius.circular(radius));
final boxPaint = Paint()
..color = color
..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;
}
}