【问题标题】:How to replace text surrounded with stars with bolded text in my message如何用我的消息中的粗体文本替换用星号包围的文本
【发布时间】:2021-11-28 21:39:58
【问题描述】:

我正在制作一个聊天应用程序,我想添加一个功能,如果用户在两颗星 (*) 之间键入文本,两颗星之间的文本 bold

例如,如果用户键入消息为*this is bold* and this is not,则星号之间的消息是粗体,如果不是粗体,则星外的消息。

我无法理解这样做的逻辑。我目前写的代码是:

    String[] boldChecker = chatMessage.message.split("\\*");
                for (int i = 0; boldChecker.length > i ; i++){
                    if ((i % 2) == 0) {
                        //is even and not bold
                        Log.d("boldArea - No",boldChecker[i]);
                    } else {
                        //is odd and bold
                        Log.d("boldArea - Yes",boldChecker[i]);
                    }
                }

这里的chatmessage.message 是用户输入的消息。我唯一知道的是要将文本设置为粗体,我需要使用html.fromHtml(<b>bold text</b>)

【问题讨论】:

标签: java android text formatting logic


【解决方案1】:

您可以继续使用这种方法:

只需将 * 对替换为 <b> </b> 标记,然后使用 Html.fromHtml(message) 使消息变为粗体,无论用户在 * 对之间键入消息的位置

像这样:
let message = "*这是粗体*​​,这不是 *"
然后更改 message = "This is bold and this is not *"

您可以使用此代码进行替换


        // Let the message typed by the user is this
        String msg = "Hello friends, *This is the bold text* and this is not but *this is also bold* ** *";

        /**
         * @params firstIndex = index of the first * of the pair we are looking in the msg string
         *         secondIndex = index of the second * of the pair
         *         pairCount = to help us acknowledge that the pair *, we are looking for, is ready
         */
        int firstIndex = 0, secondIndex = 0, pairCount = 0;

        int i = 0;
        while (true){

            char c = msg.charAt(i);

            if (c == '*'){
                if (pairCount == 0) {
                    pairCount += 1;
                    firstIndex = i;
                }
                else if (pairCount == 1) {
                    pairCount += 1;
                    secondIndex = i;
                }
            }

            if (pairCount == 2){

                // replacing first * with <b>
                msg = msg.substring(0,firstIndex) + "<b>" + msg.substring(firstIndex+1);


                // replacing second * with </b>
                // increasing secondIndex by 2
                // because length of "msg" is increased by 2
                // after replacing <b> with *
                secondIndex += 2;
                msg = msg.substring(0,secondIndex) + "</b>" + msg.substring(secondIndex+1);


                // changing pair count to 0 as we have replaced the * pair
                // and are looking for new pair
                pairCount = 0;


                // Increasing i value to 5 because we have added <b> and </b> (total length = 7)
                // on replacement of * pairs (total length = 2)
                // 7 - 2 = 5
                i += 5;

            }

            i += 1;

            if (i >= msg.length()) break;
        }


        // Set the text to the TextView using Html 
        TextView tv = findViewById(R.id.your_textview_id);
        tv.setText(Html.fromHtml(msg));

结果

希望对你有帮助?

【讨论】:

    【解决方案2】:

    您可以使用StyleSpan 将文本的星标部分加粗。

    程序如下:

    1. 创建一个正则表达式以将文本包围在两颗星之间。

      这里是:"\\*(.*?)\\*"

    2. 获取与步骤 1 中的正则表达式匹配的消息文本的匹配器

      Pattern.compile("\\*(.*?)\\*").matcher(text)

    3. 遍历匹配器并使用StyleSpan将匹配的组加粗;但是你需要在添加跨度之前删除开始的问题,如果你使用匹配器索引,这将导致IndexOutOfBoundsException;因此,我们将添加一个计数器,每次启动都会计数,并通过该计数器减少匹配器索引。

    4. 使用setSpan()设置粗体范围

    代码演示为cmets:

    private Matcher getMatchedStars(String text) {
        // matching start & end stars with a regex
        return Pattern.compile("\\*(.*?)\\*").matcher(text);
    }
    
    private Spannable getBolded(String text, Matcher matcher) {
    
        // Remove the starts from the text
        String noStarText = text.replace("*", "");
    
        // Create the Spannable from the no start text
        Spannable spannable = new SpannableString(noStarText);
    
        // count represents the current no. of removed stars
        int count = 1;
    
        // Iterate over the matched bolded text
        while (matcher.find()) {
            spannable.setSpan(new StyleSpan(BOLD),
                    matcher.start() - count, // remove all previous stars from the start index
                    matcher.end() - count - 1, // remove all previous stars from the end index
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            count += 2; // Add 2 to remove 2 stars from the current iteration (i.e. a complete bolded text is finished)
        }
        return spannable;
    }
    

    测试:

    TextView tv = findViewById(R.id.my_textview);
    String text = "Hello *Java* But here is *Android*, \n wait it's *Kotlin*";
    Spannable spannable = getBolded(text, getMatchedStars(text));
    tv.setText(spannable);
    

    【讨论】:

    • 这也有效。谢谢
    • 有两个问题需要解决。 count 代表当前编号。移除的星数在开始时需要为 0。 matcher.end() - count - 1 也是错误的,因为你需要减去 2 颗星。
    猜你喜欢
    • 2017-12-18
    • 2012-04-27
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    相关资源
    最近更新 更多