如何使单词的特定字符加粗?

时间:2021-02-11 12:29:00

标签: c# xaml xamarin xamarin.forms

我想将字符串的特定字符加粗。例如我有一个字符串:

“你好 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 或任何其他方式来实现这一点,我们不必将字符串分成小部分。

4 个答案:

答案 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。

效果:

enter image description here

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,第一个参数是开始,第二个参数是长度。

效果:

enter image description here

答案 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}}"/>

输出 enter image description here

答案 3 :(得分:0)

您可以使用以下资源使用本地化字符串:

  1. 在某处创建一个 .resx 文件

  2. 将 .resx 文件的命名空间添加到您的页面

xmlns:loc="clr-namespace:MyApp.Properties"
  1. 使用资源代替硬编码文本
<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>
相关问题