10

i have a 3 String like this:

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

what i wanted to do is get username and city name in different color with its click event.

what i m able to achive is get username by splitting to ":" character. but i dont know how to get city name and click event of both.

In city name only last city color is changing, how to change both city name color and get its click event.

this is what i tried:

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

and this is what i get as output:

enter image description here

and this is what i really expected:

enter image description here

Sagar Chavada
  • 5,169
  • 7
  • 40
  • 67
  • https://stackoverflow.com/questions/10696986/how-to-set-the-part-of-the-text-view-is-clickable – vlatkozelka Sep 05 '17 at 09:27
  • as for how to get data from a text, try to format your String some way that is easier to parse rather than using split(), maybe a json. – vlatkozelka Sep 05 '17 at 09:28
  • i tried with your link but with that i can get click event but not able to set color.. – Sagar Chavada Sep 05 '17 at 09:28
  • thing is string is dynamic so i cant set start and end position for span. – Sagar Chavada Sep 05 '17 at 09:31
  • @vlatkozelka what do you mean format your string some way.. thats what i m doing.. any idea which way is better than split. – Sagar Chavada Sep 05 '17 at 09:33
  • I think you are using adapter to show the data, then in the city column use four textview first one is for the message "There is package waiting for you to pick from" not second textview change its color set onclick listener and set the first city name same with second one. Hope you get it, – Reyansh Mishra Sep 08 '17 at 20:27
  • [Regex](https://stackoverflow.com/tags/regex/info) for the rescue! – Onik Sep 08 '17 at 20:37
  • 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); Check these lines you are replacing the samething place1 and place 2 in places1 – user3808887 Sep 12 '17 at 06:06
  • @user380887 i knew.. its solved already, thank you though – Sagar Chavada Sep 12 '17 at 06:10

6 Answers6

4

use Regex for this.

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

output will be:

surat 
mumbai
Vinay
  • 732
  • 5
  • 8
  • but how to make that final string.., i applied your solution, i get surat and mumbai as output, i also colored both places, now how to add to textview as a final output – Sagar Chavada Sep 05 '17 at 09:56
4

To extract the final description with clickable hashtags, add a hidden LinearLayout in your list item layout:

<LinearLayout
        android:id="@+id/layoutDescription"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="24dp"
        android:orientation="horizontal"
        android:visibility="gone" />

Modify your code to separate the hashtags with dynamic TextViews and add them back in the 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());
    }

The final output,

enter image description here

Prokash Sarkar
  • 11,723
  • 1
  • 37
  • 50
4

I think you have done with username and facing problem with click on city so I have given answer with click on city name.

Thanks to @Vinay for given some hint.

Please check below code.

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

Output Screenshot:

enter image description here

Niranj Patel
  • 32,980
  • 10
  • 97
  • 133
3

Try this library. It is a hash-tag implementation which works for # only. It may help you after enhancing this library for your requirement.

user320676
  • 394
  • 2
  • 19
1

Use SpannableString, youd don't need any special character, just know clickable word index. Like bellow:

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);
Fakhriddin Abdullaev
  • 4,169
  • 2
  • 35
  • 37
0

This code change the color of 'here' word in string and make clickable 'here' word only

String str  = "if you want to download This movie please click here";
SpannableString s = new SpannableString(str);
int start = str.indexOf("here");
int end =  start + "here".length();

String[] words = textfinal.split(" ");
for(final String word : words){
    if(word.startsWith("here")){
        ClickableSpan clickableSpan = new ClickableSpan() {
            @Override
            public void onClick(View textView) {
                //use word here to make a decision
                Toast.makeText(MainActivity.this, word, Toast.LENGTH_SHORT).show();
            }
        };

        s.setSpan(clickableSpan, textfinal.indexOf(word), textfinal.indexOf(word) + word.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
}
s.setSpan(new ForegroundColorSpan(Color.BLUE), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
temp.setText(s , TextView.BufferType.SPANNABLE);
temp.setMovementMethod(LinkMovementMethod.getInstance());

Adnan Bashir
  • 645
  • 4
  • 8