部分文本可在Xamarin标签中单击

时间:2016-11-14 15:39:00

标签: xamarin xamarin.forms

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

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)。我可以根据需要添加多个CharSequences以及不可点击的字符串。

我希望能在Xamarin中做到这一点,但我还没有找到解决方案。我已经考虑过自定义渲染器的可能性,但我认为如果可能的话,跨平台解决方案会更好。我对iOS的熟悉程度要低得多,但似乎可以将NSMutableAttributedString对象添加到UILabel以达到类似的效果。我也见过FancyLabel对象。我不太确定如何为UWP做这件事,因为我在研究中找不到多少。

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:3)

这个答案可能是非常事后的,但可能在将来帮助其他人。

我已经完成并测试过的是使用一个网格,你的字符串被恰当地分开,比如说你想改变一个单词的行为:
在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>

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

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

*测试Xamarin.Forms 2.3.4.247

答案 1 :(得分:3)

只需使用Xamarin Forms 3.4(及更高版本)对此提供更新的答案。您可以使用FormattedText的{​​{1}}属性。在Xamarin Docs中有关于如何使用它的深入概述。

从根本上讲,它的工作原理如下:

Label

在上面,点击文本<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

答案 2 :(得分:1)

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

EG。我需要写&#34;通过注册,您同意服务条款和隐私政策&#34;有一些格式:

  1. 不同颜色且可以点击的服务条款
  2. 不同颜色的隐私政策,可以点击
  3. 字符串的其余部分应该很简单。

    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());
    }
    

    可以执行字符串的不同格式设置,适用于跨平台。