Xamarin.Forms iOS端Label设置LineHeight后删除线Strikethrough失效问题
问题原因
这是Xamarin.Forms iOS端的已知渲染bug:iOS原生UILabel通过NSParagraphStyle设置行高后,段落样式的渲染优先级会高于默认文本装饰属性,导致删除线效果被覆盖不显示,Android端无此逻辑所以表现正常。
可行解决方案
方案1:使用自定义渲染器(兼容性最好)
1. 共享项目中创建自定义Label类
public class StrikethroughLabel : Label { }
2. iOS项目中添加对应渲染器
using UIKit; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; using Foundation; using System.ComponentModel; [assembly: ExportRenderer(typeof(StrikethroughLabel), typeof(StrikethroughLabelRenderer))] namespace YourAppNamespace.iOS.Renderers { public class StrikethroughLabelRenderer : LabelRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Label> e) { base.OnElementChanged(e); if (Control != null && Element != null) { RefreshStrikethrough(); } } protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); if (e.PropertyName is nameof(Label.TextDecorations) or nameof(Label.LineHeight) or nameof(Label.Text)) { RefreshStrikethrough(); } } private void RefreshStrikethrough() { if (!Element.TextDecorations.HasFlag(TextDecorations.Strikethrough)) return; var attributedText = new NSMutableAttributedString(Control.AttributedText); attributedText.AddAttribute( UIStringAttributeKey.StrikethroughStyle, NSNumber.FromInt32((int)NSUnderlineStyle.Single), new NSRange(0, attributedText.Length) ); Control.AttributedText = attributedText; } } }
3. 页面中使用
替换原来的Label为StrikethroughLabel,正常配置删除线和行高即可:
<local:StrikethroughLabel Text="测试文本" TextDecorations="Strikethrough" LineHeight="1.5" />
方案2:使用FormattedText(无需写原生代码)
如果不想新增自定义渲染器,可以通过FormattedString包裹文本,Span单独设置属性即可生效:
<Label LineHeight="1.5"> <Label.FormattedText> <FormattedString> <Span Text="测试文本" TextDecorations="Strikethrough" LineHeight="1.5" /> </FormattedString> </Label.FormattedText> </Label>
该方案适配Xamarin.Forms 4.8及以上版本,不需要额外修改原生代码。
注意事项
Xamarin.Forms 5.0 版本官方曾尝试修复该问题,但iOS 15及以上系统仍有偶现失效的情况,上述两种方案均可稳定兼容所有支持的iOS系统版本。
内容的提问来源于stack exchange,提问作者Divyesh
相关产品推荐
相关产品推荐

