Monday 3 August 2015

making #hashtag and @usertag clickable to a textview same as twitter with a single string

Hello all,

Today I am going to share a very nice example for making #hashtag and @user_name is clickable in a  single string .

I have tried many example for this,  but now it is working

First I have make a textview in the layout , I am assuming that the layout design is not needed to share , as It is simply a textview (having the is textview1) in a Relative Layout.

Now I have to add two base classes which is used to get the symbols(#, @) in the string

I have made two base classes one is for the @ symbol and another is for # symbol. If you want to make string clickable on any other symbol alos like: $ then you have to make another base class for $ symbol also, But for now I will work with the two base classes for the two symbols .

One base class name is :  Hashtag.java  (This class is for # symbol)

import android.content.Context;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.style.ClickableSpan;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class Hashtag extends ClickableSpan{
Context context;
TextPaint textPaint;
    public Hashtag(Context ctx) {
   super();
   context = ctx;
}

@Override
public void updateDrawState(TextPaint ds) {
   textPaint = ds;
  ds.setColor(ds.linkColor);
   ds.setARGB(255, 30, 144, 255);
}

@Override
public void onClick(View widget) {
   TextView tv = (TextView) widget;
   Spanned s = (Spanned) tv.getText();
   int start = s.getSpanStart(this);
   int end = s.getSpanEnd(this);
   String theWord = s.subSequence(start + 1, end).toString();
   // you can start another activity here 
   Toast.makeText(context, String.format("Tag : %s", theWord), 10 ).show();

}

}


Another base class name is :  CalloutLink.java  (This class is for @ symbol)

import android.content.Context;
import android.graphics.Color;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.style.ClickableSpan;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class CalloutLink extends ClickableSpan {
Context context;
public CalloutLink(Context ctx) {
   super();
   context = ctx;
}

@Override
public void updateDrawState(TextPaint ds) {
 ds.setARGB(255, 51, 51, 51);
 ds.setColor(Color.RED);

}

@Override
public void onClick(View widget) {
   TextView tv = (TextView) widget;
   Spanned s = (Spanned) tv.getText();
   int start = s.getSpanStart(this);
   int end = s.getSpanEnd(this);
   String theWord = s.subSequence(start + 1, end).toString();
  // you can start another activity here 
   Toast.makeText(context, String.format("Here's a cool person: %s", theWord), 10).show();
    }
}


Now let's move to the MainActivity .java 

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.libs.CalloutLink;
import com.libs.Hashtag;
import android.app.Activity;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends  Activity{

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

String str  =  "@People , You've gotta #dance like there's nobody watching,#Love like you'll never be #hurt,#Sing like there's @nobody listening,And live like it's #heaven on #earth.";

TextView txt = (TextView)findViewById(R.id.textView1);
ArrayList<int[]> hashtagSpans1 = getSpans(str, '#');
    ArrayList<int[]> calloutSpans1 = getSpans(str, '@');
    
    SpannableString commentsContent1 =
            new SpannableString(str);

   setSpanComment(commentsContent1,hashtagSpans1) ;
   setSpanUname(commentsContent1,calloutSpans1) ;
   
   txt.setMovementMethod(LinkMovementMethod.getInstance());
   txt.setText(commentsContent1);
}
public ArrayList<int[]> getSpans(String body, char prefix) {
   ArrayList<int[]> spans = new ArrayList<int[]>();

   Pattern pattern = Pattern.compile(prefix + "\\w+");
   Matcher matcher = pattern.matcher(body);

   // Check all occurrences
   while (matcher.find()) {
       int[] currentSpan = new int[2];
       currentSpan[0] = matcher.start();
       currentSpan[1] = matcher.end();
       spans.add(currentSpan);
   }

   return  spans;
}

private void setSpanComment(SpannableString commentsContent, ArrayList<int[]> hashtagSpans) {
for(int i = 0; i < hashtagSpans.size(); i++) {
       int[] span = hashtagSpans.get(i);
       int hashTagStart = span[0];
       int hashTagEnd = span[1];

       commentsContent.setSpan(new Hashtag(MainActivity.this),
               hashTagStart,
               hashTagEnd, 0);

   }

   
}
private void setSpanUname(SpannableString commentsUname, ArrayList<int[]> calloutSpans) {
for(int i = 0; i < calloutSpans.size(); i++) {
        int[] span = calloutSpans.get(i);
        int calloutStart = span[0];
        int calloutEnd = span[1];
        commentsUname.setSpan(new CalloutLink(MainActivity.this),
                calloutStart,
                calloutEnd, 0);

    }
}

}


That's all , no permission is required in the menifest.

I am attaching the screen shot for this task:
                                                                                                                                                                 
   

 screenshots for #tag   and @username clickable textview

Please leave a comment if you have any query regarding to this example


No comments:

Post a Comment

Advanced Kotlin Coroutines : Introduction

 Hi,  Today I am unwraping the topic in Kotin world i.e. Coroutine . If you want to get started with Kotlin coroutine and ease your daily de...