如何使用单词及其点击事件获取特殊字符

Posted

技术标签:

【中文标题】如何使用单词及其点击事件获取特殊字符【英文标题】:how to get special character with word and its click event 【发布时间】:2018-02-13 12:58:51 【问题描述】:

我有一个这样的 3 字符串:

"@Username: Deliverd your order",
"YOU got trophy: KING OF COINS",
"There is a package waiting for you to pick up from #surat to #mumbai",

我想做的是通过点击事件获取不同颜色的用户名和城市名称。

我能够实现的是通过拆分为“:”字符来获取用户名。 但我不知道如何获取城市名称和两者的点击事件。

在城市名称中只有最后一个城市颜色在变化,如何同时更改城市名称颜色并获取其点击事件。

这是我尝试过的:

if (notifications.getTitle().contains(":")) 

    String[] username = notifications.getTitle().split(":");
    String uname = getColoredSpanned(username[0] + ":", "#ff7505");
    String txt = getColoredSpanned(username[1], "#000000");
    holder.txtTitle.append(html.fromHtml(uname +" " + txt));
    holder.txtTitle.setMovementMethod(LinkMovementMethod.getInstance());
 
else if (notifications.getTitle().contains("#"))

     Matcher matcher = 
            Pattern.compile("#\\s(\\w+)").matcher(notifications.getTitle());
     i=0;
     while (matcher.find())
     
           place.add(i, matcher.group(1));
           i++;
     
     String place1 = getColoredSpanned("#" + place.get(0), "#237BCD");
     String place2 = getColoredSpanned("#" + place.get(1), "#237BCD");
     places1 = notifications.getTitle().replace("#" + place.get(0), place1);
     places1 = notifications.getTitle().replace("#" + place.get(1), place2);
     holder.txtTitle.setText(Html.fromHtml(places1));

else

    holder.txtTitle.setText(notifications.getTitle());


private String getColoredSpanned(String text, String color) 
    String input = "<font color=" + color + ">" + text + "</font>";
    return input;

这就是我得到的输出:

这是我真正期望的:

【问题讨论】:

***.com/questions/10696986/… 至于如何从文本中获取数据,请尝试以某种更易于解析的方式格式化您的字符串,而不是使用 split(),也许是 json。 我尝试了你的链接,但我可以得到点击事件但无法设置颜色.. 事情是字符串是动态的,所以我不能设置跨度的开始和结束位置。 @vlatkozelka 你的意思是用某种方式格式化你的字符串。这就是我正在做的事情。知道哪种方式比拆分更好。 【参考方案1】:

我认为您已经完成了用户名并面临点击城市的问题,所以我已经通过点击城市名称给出了答案。

感谢@Vinay 提供一些提示。

请检查以下代码。

public void setSpan() 
        String test = "There is a package waiting for you to pick up from #surat to #mumbai";
        SpannableString spannable = new SpannableString(test);
        final Matcher matcher = Pattern.compile("#\\s*(\\w+)").matcher(test);
        while (matcher.find()) 
            final String city = matcher.group(1);
            ClickableSpan clickableSpan = new ClickableSpan() 
                @Override
                public void onClick(View textView) 
                    Toast.makeText(mActivity, city, Toast.LENGTH_SHORT).show();
                

                @Override
                public void updateDrawState(TextPaint ds) 
                    super.updateDrawState(ds);
                    ds.setUnderlineText(false);
                    ds.setColor(Color.RED);
                
            ;
            int cityIndex = test.indexOf(city) - 1;
            spannable.setSpan(clickableSpan, cityIndex, cityIndex + city.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        
        mTextViewNotification.setText(spannable);
        mTextViewNotification.setMovementMethod(LinkMovementMethod.getInstance());
    

输出截图:

【讨论】:

它只适用于“#”吗?因为我有其他带有“$”符号的文本,并且 doller 符号模式不匹配。 并带有“@”符号,它总是出现类似 java.lang.IndexOutOfBoundsException: setSpan (-2 ... 7) 在 0 之前开始的错误 您必须将此逻辑保留在此 else if (notifications.getTitle().contains("#")) 部分 我知道..我把它保留为“#”值..但我在谈论@和 $ 符号..它在 Pattern.compile 中不起作用,关于“@”符号的任何想法.. 【参考方案2】:

为此使用正则表达式。

String str= "There is a package waiting for you to pick up from #surat to #mumbai";

Matcher matcher = Pattern.compile("#\\s*(\\w+)").matcher(str);
while (matcher.find()) 
  System.out.println(matcher.group(1));

输出将是:

surat 
mumbai

【讨论】:

但是如何制作最终的字符串..,我应用了您的解决方案,我得到了 surat 和 mumbai 作为输出,我还为这两个地方着色,现在如何添加到 textview 作为最终输出【参考方案3】:

要提取带有可点击主题标签的最终描述,请在列表项布局中添加隐藏的LinearLayout

<LinearLayout
        android:id="@+id/layoutDescription"
        android:layout_
        android:layout_
        android:layout_margin="24dp"
        android:orientation="horizontal"
        android:visibility="gone" />

修改您的代码以将主题标签与动态TextViews 分开并将它们添加回LinearLayout

if (notifications.getTitle().contains(":")) 
        String[] username = notifications.getTitle().split(":");
        String pre_username = getColoredSpanned(username[0] + ":", "#ff7505");
        String post_username = getColoredSpanned(username[1], "#000000");
        holder.txtTitle.append(Html.fromHtml(pre_username + " " + post_username));
        holder.txtTitle.setMovementMethod(LinkMovementMethod.getInstance());
    
    else if (notifications.getTitle().contains("#")) 
        layoutDescription.setVisibility(View.VISIBLE);

        Matcher matcher = Pattern.compile("#\\s(\\w+)").matcher(notifications.getTitle());

        List<String> place = new ArrayList<>();
        int i = 0;
        while (matcher.find()) 
            place.add(i, matcher.group(1));
            i++;
        

        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.setMargins(5, 0, 5, 0); // (left, top, right, bottom)

        TextView mHashTagA = new TextView(this);
        mHashTagA.setLayoutParams(layoutParams);
        mHashTagA.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                Toast.makeText(getApplicationContext(), "Clicked on HashTag A", Toast.LENGTH_SHORT).show();
            
        );

        TextView mSeparator = new TextView(this);
        mSeparator.setLayoutParams(layoutParams);
        mSeparator.setText("to");

        TextView mHashTagB = new TextView(this);
        mHashTagB.setLayoutParams(layoutParams);
        mHashTagB.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                Toast.makeText(getApplicationContext(), "Clicked on HashTag B", Toast.LENGTH_SHORT).show();
            
        );

        TextView mDescription = new TextView(getApplicationContext());
        mDescription.setTextColor(Color.parseColor("#343434"));
        mDescription.setLayoutParams(layoutParams);

        String place1 = getColoredSpanned("#" + place.get(0), "#237BCD");
        mHashTagA.setText(Html.fromHtml(place1));

        String place2 = getColoredSpanned("#" + place.get(1), "#237BCD");
        mHashTagB.setText(Html.fromHtml(place2));

        String without_hash = notifications.getTitle().split("#")[0];
        mDescription.setText(without_hash);

        layoutDescription.addView(mDescription);
        layoutDescription.addView(mHashTagA);
        layoutDescription.addView(mSeparator);
        layoutDescription.addView(mHashTagB);
     else 
        layoutDescription.setVisibility(View.GONE);
        holder.txtTitle.setText(notifications.getTitle());
    

最终输出,

【讨论】:

看起来很完美。 看起来很有希望.. 我会尽快尝试.. 那么用户点击事件呢【参考方案4】:

试试this library。它是一个井号标签实现,仅适用于 # 。根据您的要求增强此库后,它可能会对您有所帮助。

【讨论】:

不错的图书馆...是的,它可能会有所帮助...谢谢。【参考方案5】:

使用 SpannableString,你不需要任何特殊字符,只知道可点击的词索引。如下:

SpannableString styledString
            = new SpannableString("There is a package waiting for you to pick up from " +
            "surat" +  // index 51 - 56
            " to " +
            "mumbai"); //index 60 - 66

    // clickable text for "surat"
    ClickableSpan clickableSpan1 = new ClickableSpan() 

        @Override
        public void onClick(View widget) 
            // We display a Toast. You could do anything you want here.
            Toast.makeText(MainActivity.this, "surat clicked", Toast.LENGTH_SHORT).show();

        
    ;

    // clickable text for "mumbai"
    ClickableSpan clickableSpan2 = new ClickableSpan() 

        @Override
        public void onClick(View widget) 
            // We display a Toast. You could do anything you want here.
            Toast.makeText(MainActivity.this, "mumbai clicked", Toast.LENGTH_SHORT).show();

        
    ;

    styledString.setSpan(clickableSpan1, 51, 56, 0);
    styledString.setSpan(clickableSpan2, 60, 66, 0);

    textView.setText(styledString);

【讨论】:

以上是关于如何使用单词及其点击事件获取特殊字符的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xcode10 Ui 测试中点击标签的特定单词?

如何使用 jQuery 同步运行事件触发器及其绑定方法?

如何从包含特殊字符的字符串中找出单词

如何在不使用坐标方法的情况下在 XCode UI 测试中点击字符串语句的特定部分/单词

android跨度点击事件

如何使用Vue.js中的按钮点击事件并获取按钮属性