我想将字符串的特定字符加粗。例如我有一个字符串:
“你好 Dev!你好吗?”
在这里我想让 Dev 的角色 D 加粗。
我可以像这样使用格式化字符串来做到这一点:
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Hello" />
<Span Text=" D" FontAttributes="Bold"/>
<Span Text="ev!" />
<Span Text=" How are you?" />
</FormattedString>
</Label.FormattedText>
</Label>
但这就是问题所在。我必须通过本地化来执行此操作。也就是说,文本将以 3 种不同的语言出现。在那个地方改变了这个词。
另一个问题是我必须将字符串分成许多小部分。那么有谁知道我们如何使用 Converter 或任何其他方式来实现这一点,我们不必将字符串分成小部分。
答案 0 :(得分:1)
一种解决方案是将“逻辑”放在 ViewModel 中:
public class ViewModel
{
public string StringBeforeBold {get;set;}
public string StringBold {get;set}
public string StringAfterBold {get;set;}
}
xaml 代码可能是这样的
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding StringBeforeBold}" />
<Span Text="{Binding StringBold}" FontAttributes="Bold"/>
<Span Text="{Binding StringAfterBold}" />
</FormattedString>
</Label.FormattedText>
</Label>
答案 1 :(得分:1)
您可以使用 LabelRenderer/SpannableString 在每个平台(Android/iOS)中自定义 NSMutableAttributedString 来实现这一点。您可以使用 Range
索引和 start
索引中的 end
来设置需要为 Bold
设置 Label
的位置。
在 Xamarin Forms 中创建一个 CustomLabel:
public class CustomLabel : Label
{
public static readonly BindableProperty StartPositionProperty = BindableProperty.Create("StartPosition", typeof(int), typeof(CustomLabel), null);
public int StartPosition
{
get { return (int)GetValue(StartPositionProperty); }
set { SetValue(StartPositionProperty, value); }
}
public static readonly BindableProperty EndPositionProperty = BindableProperty.Create("EndPosition", typeof(int), typeof(CustomLabel), null);
public int EndPosition
{
get { return (int)GetValue(EndPositionProperty); }
set { SetValue(EndPositionProperty, value); }
}
public static readonly BindableProperty BoldLengthProperty = BindableProperty.Create("BoldLength", typeof(int), typeof(CustomLabel), null);
public int BoldLength
{
get { return (int)GetValue(BoldLengthProperty); }
set { SetValue(BoldLengthProperty, value); }
}
}
在 Xaml 中使用它,如下所示:
<local:CustomLabel x:Name="mylabel"
Text="Hello Dev! How are you?"
FontSize="Large"
StartPosition="6"
EndPosition="7"
BoldLength="1"
VerticalOptions="CenterAndExpand"/>
然后在 Android 解决方案中创建 CustomLabelRenderer(这里开始和结束是硬编码,您可以为 CustomLabel 添加 Bindable property 以使其灵活):>
public class CustomLabelRenderer: LabelRenderer
{
public CustomLabelRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
CustomLabel customLabel = e.NewElement as CustomLabel;
if (Control != null)
{
SpannableString spannableString = new SpannableString(e.NewElement.Text);
StyleSpan styleSpan_B = new StyleSpan(TypefaceStyle.Bold);
spannableString.SetSpan(styleSpan_B, customLabel.StartPosition, customLabel.EndPosition, SpanTypes.InclusiveExclusive);
Control.SetText(spannableString,TextView.BufferType.Spannable);
}
}
}
注意:关于SetSpan
方法,第二个参数是start,第三个参数是end。
效果:
在 iOS 解决方案中,还要创建 CustomLabelRenderer:
public class CustomLabelRenderer: LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
CustomLabel customLabel = e.NewElement as CustomLabel;
if (Control != null)
{
var attributedString = new NSMutableAttributedString(e.NewElement.Text);
var BoldTextAttributes = new UIStringAttributes
{
Font = UIFont.FromName("Helvetica-Bold", 30f)
};
attributedString.SetAttributes(BoldTextAttributes.Dictionary, new NSRange(customLabel.StartPosition, customLabel.BoldLength));
Control.AttributedText = attributedString;
}
}
}
注意:关于NSRange
,第一个参数是开始,第二个参数是长度。
效果:
答案 2 :(得分:0)
@Junior Jiang 感谢您分享您的想法,它确实有效。
但是我用 Converter 得到了我的解决方案。我在这里分享我的解决方案,以便它可以对正在寻找相同解决方案的人有所帮助。
StringToFormattedTextConverter
public class StringToFormattedTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
if (value == null)
{
return new FormattedString();
}
else
{
var val = (string)value;
string pattern = "D";
var fText = new FormattedString();
string[] substrings = Regex.Split(val, pattern);
/* String will be splitted in 3 parts
[0] Hello
[1] D [Bold]
[2] ev! How are you?
*/
if (substrings != null && substrings.Count() >= 0)
{
fText.Spans.Add(new Span { Text = substrings[0], FontFamily = "RobotoRegular" });
fText.Spans.Add(new Span { Text = "D", FontFamily = "RobotoBold" });
fText.Spans.Add(new Span { Text = substrings[1], FontFamily = "RobotoRegular" });
}
Debug.WriteLine($"Final Formatted Text - {fText}");
return fText;
}
}
catch (Exception ex)
{
Debug.WriteLine($"Exception - {ex.Message}");
}
return (string)value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
在 App.xaml 即资源字典中声明它
<Application.Resources>
<!--Converters-->
<converters:StringToFormattedTextConverter x:Key="StringToFormattedTextConverter" />
</Application.Resources>
像这样使用标签:
<Label HorizontalOptions="Center"
VerticalOptions="Start"
FormattedText="{Binding WelcomeText,
Converter={StaticResource StringToFormattedTextConverter}}"/>
答案 3 :(得分:0)
您可以使用以下资源使用本地化字符串:
在某处创建一个 .resx 文件
将 .resx 文件的命名空间添加到您的页面
xmlns:loc="clr-namespace:MyApp.Properties"
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="{x:Static loc:Resources.Hello}" />
<Span Text=" " />
<Span Text="{x:Static loc:Resources.Dev}" FontAttributes="Bold"/>
<Span Text="! " />
<Span Text="{x:Static loc:Resources.HowAreYou}" />
<Span Text="?" />
</FormattedString>
</Label.FormattedText>
</Label>