4

I have a string that has specific words I want to color. Those words are the one's that start with #.

    if(title.contains("#")){

        SpannableString WordtoSpan = new SpannableString(title);   

        int idx = title.indexOf("#");
        if (idx >= 0) {

            Pattern pattern = Pattern.compile("[ ,\\.\\n]");
            Matcher matcher = pattern.matcher(title);
            int wordEnd = matcher.find(idx)? matcher.start() : -1;

            if (wordEnd < 0) {
                wordEnd = title.length();
            }
            WordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE),
                        idx,
                        wordEnd,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }           

        holder.txtTitle.setText(WordtoSpan);
    } else {
        holder.txtTitle.setText(title);
    }

Now lets take for example this string Bold part is for example the colored words.

I love cheese #burgers, and with #ketchup.

^ This is my current thing with my code. What I want is to color every # word, not just first one.

ex. It'll be like

I love cheese #burgers, and with #ketchup.

I think I need to loop? But couldn't get it clearly and working x.x


Update: Latest try. List becomes blank.

    SpannableString WordtoSpan = new SpannableString(title);

    int end = 0;

    Pattern pattern = Pattern.compile("[ ,\\.\\n]");
    Matcher matcher = pattern.matcher(title);

    int i = title.indexOf("#");

    for (i = 0; i < title.length(); i++) {
    if (i >= 0) {

        int wordEnd = matcher.find(i)? matcher.start() : -1;

        if (wordEnd < 0) {
            wordEnd = title.length();
        }
        WordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE),
                    i,
                    wordEnd,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        i = end;
    }    

    holder.txtTitle.setText(WordtoSpan);
    }
John Jared
  • 790
  • 3
  • 16
  • 40

5 Answers5

7

I had provided this answer earlier here - https://stackoverflow.com/a/20179879/3025732

String text = "I love chicken #burger , cuz they are #delicious";
//get the text from TextView

Pattern HASHTAG_PATTERN = Pattern.compile("#(\\w+|\\W+)");
Matcher mat = HASHTAG_PATTERN.matcher(text);

while (mat.find()) {
  String tag = mat.group(0);

  //String tag will contain the hashtag
  //do operations with the hashtag (change color)
}

[EDIT]

I've modified the code and done it according to what you need:

SpannableString hashText = new SpannableString(text.getText().toString());
Matcher matcher = Pattern.compile("#([A-Za-z0-9_-]+)").matcher(hashText);
while (matcher.find())
{
     hashText.setSpan(new ForegroundColorSpan(Color.BLUE), matcher.start(), matcher.end(), 0);
}
text.setText(hashText);

Here's a screenshot of it:

enter image description here

Community
  • 1
  • 1
Joel Fernandes
  • 4,776
  • 2
  • 26
  • 48
4

I'm surprised that no one has mentioned this:

// String you want to perform on
String toChange = "I love cheese #burgers, and with #ketchup.";

// Matches all characters, numbers, underscores and dashes followed by '#'
// Does not match '#' followed by space or any other non word characters
toChange = toChange.replaceAll("(#[A-Za-z0-9_-]+)", 
                         "<font color='#0000ff'>" + "$0" +  "</font>");

// Encloses the matched characters with html font tags

// Html#fromHtml(String) returns a Spanned object
holder.txtTitle.setText(Html.fromHtml(toChange));

#0000ff ==>> Color.BLUE

Screenshot:

enter image description here

Vikram
  • 51,313
  • 11
  • 93
  • 122
  • @JohnJared Added a screenshot above. Could the problem be somewhere else in your code? – Vikram Nov 27 '13 at 19:15
  • Umm, found out why. Cuz in my app I have arabic letter with # thats i why, but when I changed arabic to eng they worked. How can I make it color arabic words too? – John Jared Nov 27 '13 at 19:21
  • أ ب ت ث ج ح خ د ذ ل ز ر ع غ ف ق س ش ص ض ط ظ م ر ه ن و ي – John Jared Nov 27 '13 at 19:23
  • I should wait 16 hrs, after 16 hrz ill give u the +50, thanks! – John Jared Nov 27 '13 at 19:27
  • @JohnJared You are welcome. Thanks for the accept. Here's another answer of mine following a slightly different approach, but accomplishing the same output: [How to color text using Regex in android](http://stackoverflow.com/a/17849313/2558882). – Vikram Nov 27 '13 at 19:39
  • @JohnJared Just wondering: was there something wrong with my answer? – Vikram Nov 29 '13 at 16:01
  • 1
    Nope, but I gave that person +50 by mistake x.x sorry. I'll start another bounty on the next question I ask and I will reward you it. I am very sorry – John Jared Nov 30 '13 at 15:24
  • @JohnJared Hey, this has happened to me before: [here](http://stackoverflow.com/questions/18535473/activity-has-leaked-window-that-was-originally-added-here-other-issues-concer/18564353#18564353)!! Lol. If it was a mistake, no harm, no foul. Please don't start another question to reward me. I was merely confused as to whether my answer was alright. – Vikram Nov 30 '13 at 16:42
  • check this out, http://stackoverflow.com/questions/20427398/android-matcher-and-patter-cut-up-from-the-link – John Jared Dec 06 '13 at 15:17
  • @JohnJared Saw your comment too late :) – Vikram Dec 07 '13 at 19:44
  • Hello, I am using this code `" + "$0" + "` . But in my case ex is "#abc xyz". But it is coloring only #abc. How to consider whole string "#abc xyz". – Shyamaly Lakhadive Jan 22 '21 at 09:34
  • @ShyamalyLakhadive I think `Joel Fernandes's` answer outlines a better approach. You'll still need to come up with a way to isolate the substring that needs to be colored - either by using regex or by some calculation. – Vikram Jan 22 '21 at 20:47
  • @Vikram I tried with different regular expression but either it color complete text present in edittext or not a single word. I tried many regular expression. – Shyamaly Lakhadive Jan 24 '21 at 03:53
1

You need to loop through your matches. There is a previous post you can have a look at here:

Finding Multiple Integers Inside A String Using Regex

Community
  • 1
  • 1
  • It's fine to find them(I can use .split("#"), but how to find them **and** color them inside the string at the same time? – John Jared Nov 25 '13 at 12:50
  • if(title.contains("#")){ Matcher matcher = pattern.matcher(title); while ( matcher.find() ) { //do ForegroundcolorSpan etc } } – Anders Ludvigsson Nov 27 '13 at 13:53
1

Check following example :

String title = "Your #complete sentence #testing #test.";
printUsingNormal(title);
printUsingRegex(title);

private static void printUsingRegex(String title) {
    Pattern pattern = Pattern.compile("[ ,\\.\\n]");

    int start = 0;
    int end = 0;
    Matcher matcher = pattern.matcher(title);
    while (end >= 0 && end < title.length()) {
        start = title.indexOf('#', start);
        if (start > 0) {
            end = matcher.find(start) ? matcher.start() : -1;
            if (end > 0) {
                System.out.println("Word : " + title.substring(start, end)
                        + " Start : " + start + " End : " + end);
                start = end;
            }
        } else {
            break;
        }
    }
}

private static void printUsingNormal(String title) {
    int start = 0;
    for (int i = 0; i < title.length(); i++) {
        char c = title.charAt(i);
        if (c == '#') {
            start = i; // Got the starting hash
            int end = title.indexOf(' ', i + 1); // Finding the next space.
            if (end > 0) {
                System.out.println("Word : " + title.substring(start, end)
                        + " Start : " + start + " End : " + end);
                i = end;
            } else {
                end=title.length()-1;
                System.out.println("Word : " + title.substring(start, end)
                        + " Start : " + start + " End : " + end);
                i = end;
            }
        }
    }
}
Eldhose M Babu
  • 14,382
  • 8
  • 39
  • 44
0

Use while(), this is the snippet for setting the background color of text searched in android native messenger, you can try the same in your code.

VenomVendor
  • 15,064
  • 13
  • 65
  • 96