【问题标题】:Partial text clickable in Xamarin LabelXamarin 标签中可单击的部分文本
【发布时间】:2019-05-12 13:10:36
【问题描述】:

我正在寻找一种方法,使 Xamarin Forms 中标签的部分文本可点击,执行不同的功能,并且理想情况下具有不同的格式。我知道可点击的标签很简单,可以这样做:

Label label = new Label { Text = "Click me" };
label.Click += () => { label.Text = "Clicked"; };

基本上,我希望模仿我在原生 Android 中完成的应用程序中的行为。我的应用程序必须适用于 Android 和 iOS,最好是 UWP。在 Android 中,可以将 CharSequence 对象添加到 TextView(类似于 Label 的控件)中。在 Android 中,我可能会像这样创建一个 CharSequence 对象:

    Runnable doSomething; //equivalent to C# Action; assuming initialized somewhere
    String myString = "My Clickable String"; //the clickable string
    Spannable span = Spannable.Factory.getInstance().newSpannable(myString); //this is the clickable text to add to TextView
        span.setSpan(new ClickableSpan() {
            @Override
            public void onClick(View v) {
                doSomething.run(); //perform the action
            }

            @Override
            public void updateDrawState(TextPaint ds) {
                ds.setUnderlineText(true); //make underlined
                ds.setColor(Color.rgb(color.r, color.g, color.b)); //change the color
                ds.setFakeBoldText(true); //make it bold
                ds.setTextSize((float) largeFont); //change the text size
            }
        }, 0, a.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //style and function for the entire string

如您所见,它执行一个功能并具有样式属性。然后我可以将它添加到 TextView(Spannable 实现 Spanned 实现 CharSequence)。除了不可点击的字符串之外,我还可以根据需要添加多个 CharSequence。

我希望有一种方法可以在 Xamarin 中执行此操作,但我还没有找到解决方案。我已经考虑过自定义渲染器的可能性,但如果可能的话,我觉得跨平台解决方案会更好。我对 iOS 不太熟悉,但似乎可以将 NSMutableAttributedString 对象添加到 UILabel 以达到类似的效果。我还看到了FancyLabel 对象。我不太确定如何为 UWP 做到这一点,因为我在研究中确实没有找到太多东西。

任何帮助将不胜感激!

【问题讨论】:

  • 我也想弄清楚这一点。我最终放弃并使用TapGestureRecognizer 使整个标签可点击。宁愿只有特定的词可点击。
  • 就我个人而言,我会创建自己的自定义控件(MyLabel : UILabel),然后我会添加两个公共整数,用于范围的开始和范围的结束。然后我会添加一个手势识别器并计算出字符串数组(label.text)中点击的索引,并添加您希望它执行的任何操作/事件。这是我头顶的一个粗略想法。
  • 目前无法使用 X.Forms 标签。请参阅:forums.xamarin.com/discussion/26882/…。 Label 有一个 FormattedString 属性,但您只能更改文本的字体、大小和颜色,不能添加指向某些文本的链接。您需要使用自定义渲染器来使用特定于平台的方法在 TextView(Android)/UILabel(iOS) 中间添加链接。或者,您也许可以使用加载了本地 HTML 的 WebView?

标签: xamarin xamarin.forms


【解决方案1】:

只是为了使用 Xamarin Forms 3.4(及更高版本)提供更新的答案。您可以使用LabelFormattedText 属性。在Xamarin Docs 中有关于如何使用它的深入概述。

基本上,它是这样工作的:

<Label 
    LineBreakMode="WordWrap">
    <Label.FormattedText>
        <FormattedString>
            <Span 
                Text="Red Bold, " 
                TextColor="Red" 
                FontAttributes="Bold" />
            <Span 
                Text="default, " 
                Style="{DynamicResource BodyStyle}">                          
                <Span.GestureRecognizers>
                    <TapGestureRecognizer Command="{Binding TapCommand}" />
                </Span.GestureRecognizers>
            </Span>
            <Span 
                Text="italic small." 
                FontAttributes="Italic" 
                FontSize="Small" />
        </FormattedString>
    </Label.FormattedText>
</Label>

在上面,点击文本default将执行TapCommand

【讨论】:

  • 这是最新的最佳答案!
【解决方案2】:

这个答案可能是事后的,但将来可能会对其他人有所帮助。

我所做和测试的是使用网格将字符串适当拆分,例如您想更改单词的行为:
在您的 ViewModel/View 中:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/> //for first few words
        <ColumnDefinition Width="Auto"/> //the target word
        <ColumnDefinition Width="Auto"/> //the rest of the string
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/> //one row for one line of text
    </Grid.RowDefinitions>

    <Label Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="0" Text="First part of string"/>
    <Label Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="0" Text="TARGET-WORD">
        <Label.GestureRecognizers>
            <TapGestureRecognizer Command="{Binding <YOUR_COMMAND>}"/>
        </Label.GestureRecognizers>  
    </Label>
    <Label Grid.Column="2" Grid.ColumnSpan="1" Grid.Row="0" Text="rest of the string"/>
</Grid>

通过这种方式,您可以隔离网格的特定部分并修改行为/美学(数据触发器、样式、手势)。请记住,&lt;Span&gt;&lt;/Span&gt; 标签不支持&lt;Label&gt;&lt;/Label&gt; 的所有功能。

显然,在 XAML 中您需要知道单词的位置,或者如果字符串是动态的,您可以动态搜索它并在后面的代码中构建您的 Grid。

*在 Xamarin.Forms 2.3.4.247 上测试

【讨论】:

  • 这是一个很好的解决方案。但是我的链接在一个长字符串的末尾: Kişisel verilerimin neden ve nerelerden toplandığı, nasıl kullanıldığı ve diğer haklarımla ilgili olarak Kişisel Verilerin Korunması Kanunu uyarınca yapılan [link]bilgilendirmeyi[/link] okudum。
【解决方案3】:

考虑一个例子来回答这个问题,这可能会对将来的人有所帮助,

例如。我需要用一些格式写“通过注册,您同意服务条款和隐私政策”:

  1. 不同颜色的服务条款,可以点击
  2. 不同颜色的隐私政策,可以点击

字符串的其余部分应该很简单。

XAML 中的代码:

`<Label Text="By signing up, you agree to the " Grid.Row="0"/>
 <Label Text="Terms of Services" TextColor="DarkOrange" WidthRequest="150" 
        HorizontalOptions="End" Grid.Row="0"> 
     <Label.GestureRecognizers>
         <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped_Terms"/>
     </Label.GestureRecognizers>
 </Label>
 <Label Text=" and " HorizontalOptions="End"  Grid.Row="0" />
 <Label Text="Privacy Policy" TextColor="DarkOrange" HorizontalOptions="Center"
        VerticalOptions="CenterAndExpand" Grid.Row="0">
     <Label.GestureRecognizers>
         <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped_Policy"/>
     </Label.GestureRecognizers>
 </Label>
`

用 C# 编写的用于点击回调的代码:

private void TapGestureRecognizer_Tapped_Terms(object sender, EventArgs e)
{
    Navigation.PushAsync(new TermsofServicesPage());
}

private void TapGestureRecognizer_Tapped_Policy(object sender, EventArgs e)
{
    Navigation.PushAsync(new PrivacyPolicyPage());
}

可以执行不同的字符串格式,并且可以在跨平台上正常工作。

【讨论】:

    猜你喜欢
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多