Flutter中如何实现文本垂直方向双色分割显示效果
实现方案
直接用TextStyle的foreground参数绑定渐变着色器即可实现和示例CSS完全一致的效果,比ShaderMask方案更稳定,不会出现渲染错位、颜色覆盖问题。
核心逻辑和CSS的实现完全对应:
- 线性渐变方向设为顶部到底部
- 渐变停点卡在50%位置做硬分界,上半部分用深蓝色、下半部分用红色
- 着色器范围直接绑定文字实际渲染尺寸,不用手动写死宽高
完整可运行示例:
import 'package:flutter/material.dart'; class SplitColorTextPage extends StatelessWidget { const SplitColorTextPage({super.key}); @override Widget build(BuildContext context) { const targetText = "测试文字内容"; const baseStyle = TextStyle(fontSize: 40, fontFamily: 'Arial'); // 提前计算文字实际渲染尺寸,给着色器提供准确范围 final textSize = (TextPainter( text: const TextSpan(text: targetText, style: baseStyle), textDirection: TextDirection.ltr, maxLines: 1, )..layout()).size; return Scaffold( body: Center( child: Text( targetText, style: baseStyle.copyWith( foreground: Paint() ..shader = const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFF0D2172), Color(0xFF0D2172), Color(0xFFFF2828), Color(0xFFFF0000), ], stops: [0, 0.5, 0.5, 1], tileMode: TileMode.clamp, ).createShader(Offset.zero & textSize), ), ), ), ); } }
之前ShaderMask方案失效的常见原因
如果坚持用ShaderMask实现,必须避开几个坑,否则效果必然不对:
- 必须把
blendMode设为BlendMode.srcIn,不然渐变不会裁剪到文字轮廓内部 - Text组件不能设置任何
color属性,不透明的文字色会直接覆盖着色器效果 - 不要给ShaderMask加多余的padding、父容器不要占满整屏,否则渐变范围会按父组件尺寸计算,分界位置就会错位
ShaderMask的正确写法参考:
ShaderMask( shaderCallback: (bounds) => const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFF0D2172), Color(0xFF0D2172), Color(0xFFFF2828), Color(0xFFFF0000), ], stops: [0, 0.5, 0.5, 1], ).createShader(bounds), blendMode: BlendMode.srcIn, child: const Text( "测试文字", style: TextStyle(fontSize: 40, fontFamily: 'Arial'), ), )
多行文字场景下,两种方案默认都会按整个文本块的总高度计算50%分界,如果需要每一行单独做上下分色,把每行文字拆成独立组件渲染即可。
内容的提问来源于stack exchange,提问作者Plopen
相关产品推荐
相关产品推荐

