Not Returning to App After Following Link - android

Content is delivered to my app from a server, sometimes the content contains tel: or mailto: hyperlinks. Currently I use html.fromhtml() and setMovementMethod to make the textview links clickable:
((TextView) findViewById(R.id.c_data)).setText(Html.fromHtml(HTML_out));
((TextView) findViewById(R.id.c_data)).setMovementMethod(LinkMovementMethod.getInstance());
and this works, allows the user to open mailto links, phone links and anything else.
The problem is it closes my app when they click the link, so if they click back from the phone or email it takes them back to the home screen instead of my app.
From what I can see, when the link is clicked for some reason onStop is called. How can I avoid this so the app will be re-opened right after the call/email?
example data:
<b>Title1</b>(44#) ###-####
<b>Title2</b>test#gmail.com
<b>Title3</b>google.ca
edit:
I tried to use an intent:
((TextView) findViewById(R.id.cust_data)).setText(Html.fromHtml(HTML_out));
//((TextView) findViewById(R.id.cust_data)).setMovementMethod(LinkMovementMethod.getInstance());
((TextView) findViewById(R.id.cust_data)).setMovementMethod(new MovementMethod() {
#Override
public void initialize(TextView widget, Spannable text) {
//Log.i("Test click","Good");
}
#Override
public boolean onKeyDown(TextView widget, Spannable text, int keyCode, KeyEvent event) {
return false;
}
#Override
public boolean onKeyUp(TextView widget, Spannable text, int keyCode, KeyEvent event) {
//Log.i("Test click","Good");
return false;
}
#Override
public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) {
//Log.i("Test click","Good");
return false;
}
#Override
public void onTakeFocus(TextView widget, Spannable text, int direction) {
}
#Override
public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event) {
return false;
}
#Override
public boolean onTouchEvent(TextView widget, Spannable text, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
Log.i("Test click", text.toString());
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:0123456789"));
startActivity(intent);
return true;
} else {
return false;
}
}
#Override
public boolean onGenericMotionEvent(TextView widget, Spannable text, MotionEvent event) {
return false;
}
#Override
public boolean canSelectArbitrarily() {
return false;
}
});
Just to text I used a static phone number. This still doesn't take me back to my app after.

From your last comment it sounds like you are going to possibly have several links inside of one textview. If that's the case then what you want is to set the text with a spannable, which allows you to determine what links are in there, what their text says, and other formatting like bold or italic text for only part of the text. Try something like this:
final SpannableStringBuilder content = getContent(); // This method is explained below.
final TextView textView = (TextView) findViewById(R.id.my_text_view);
textView.setLinksClickable(true);
textView.setText(content, TextView.BufferType.SPANNABLE);
textView.setMovementMethod(LinkMovementMethod.getInstance());
getContent() - This is where it will be more difficult to give you an answer, since we don't know how you're getting your links. When I wrote an application that did this it was pulling data from an xml file, so the links were marked in it. I will paste that code, so you can base yours off of it, but unless you are doing exactly the same as we were then you'll have to modify it to get your links.
if (contentNode instanceof Element && contentNode.getNodeName().equals("section")) {
String sectionTitle = ((Element) contentNode).getAttribute("title");
article.headers.add(sectionTitle);
NodeList sectionList = contentNode.getChildNodes();
String text = "";
ArrayList<String> links = new ArrayList<>(), linkStrings = new ArrayList<>();
for (int k = 0; k < sectionList.getLength(); k++) {
Node sectionNode = sectionList.item(k);
if (sectionNode instanceof Element && sectionNode.getNodeName().equals("text")) {
NodeList textNodes = sectionNode.getChildNodes();
for (int l = 0; l < textNodes.getLength(); l++) {
Node attributeNode = textNodes.item(l);
text += attributeNode.getTextContent();
}
}
if (sectionNode instanceof Element && sectionNode.getNodeName().equals("embedded_link")) {
String linkDestination = ((Element) sectionNode).getAttribute("destination");
String linkString = ((Element) sectionNode).getAttribute("string");
linkStrings.add(linkString);
links.add(linkDestination);
}
} // end k forloop
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text);
// Loop through all of the links.
for (int m = 0; m < links.size(); m++) {
final String linkString = linkStrings.get(m);
final String link = links.get(m);
final int start = text.indexOf(linkString);
final int end = start + linkString.length();
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View widget) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(link));
context.startActivity(i);
}
};
if (start > -1) {
try {
spannableStringBuilder.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception e) {
Log.e("couldn't spannable text", linkString);
}
}
} // end m forloop
article.bodyContent.put(sectionTitle, spannableStringBuilder);
} // end if for section
Hopefully that all isn't too confusing. If you have more questions let me know.

Related

Accessing an array inside OnKeyListener inner class

I am studying Mobile Application Developer and I am just a beginner. So, forgive me if the question is silly.
I am creating a simple Quiz App. I have MainActivity which act as a welcoming screen.
public class MainActivity extends AppCompatActivity {
private Button startBt; //the user will enter this button to go the SecondActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startBt = findViewById(R.id.startBt);
startBt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this, SecondActivity.class);
startActivity(i);
}
});
}
}
Then, I have a SecondActivity which suppose to ask the user a question and get the answer as a String and then increment the score if the answer is correct. There is 10 question. So, I want to use a loop to iterate through all questions. Also, inside the loop there is OnKeyListener which indicate when the user press Enter and compare the user answer to the saved answer.
public class SecondActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
String[] questions = getResources().getStringArray(R.array.questions);
String[] answers = getResources().getStringArray(R.array.answers);
TextView questionTv = findViewById(R.id.questionTv);
final EditText answerEt = findViewById(R.id.answerPt);
TextView scoreTv = findViewById(R.id.scoreTv);
int scoreCounter = 0;
for (int i=0; i<10; i++) {
answerEt.setText("");
scoreTv.setText(scoreCounter);
questionTv.setText(questions[i]);
answerEt.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
if (**answerEt**.getText().toString().equals(**answers[i]**)) {
Toast t = Toast.makeText(getApplicationContext(), "Correct",Toast.LENGTH_LONG);
t.show();
**scoreCounter++;**
return true;
}
else
return false;
} else
return false;
}
});
}
}
}
Now, please check the bold part of the code. I cannot access answerEt, scoreCounter, answer[i] because they are not final. They should be final because I am working with an inner class. Here is the problem, if I will make them final, I will not have the ability to modify them. However, scoreCounter should be incremented to show the user score. Also the i should be incremented to iterate through the answer[]. One will say "make them Global". Sadly, I tried this and my program crashed. So, How I can solve this?
Thanks in advance
pass on responsibility to check for correct answer to a separate function.
private boolean checkAnswer(EditText et, final int questionID) {
if (et.getText().toString().equals(answers[questionID])) {
Toast t = Toast.makeText(getApplicationContext(), "Correct", Toast.LENGTH_LONG);
t.show();
scoreCounter++;
return true; // for correct answer.
}
return false; // for incorrect answer.
}
Modify your loop to use above function like this :
for (int i = 0; i < 10; i++) {
final int currentQuestionID = i;
answerEt.setText("");
scoreTv.setText(scoreCounter);
questionTv.setText(questions[i]);
answerEt.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
return checkAnswer((EditText) (v), currentQuestionID);
}
return false;
}
});
}

Custom URLSpan don't trigger onClick event, using kotlin [duplicate]

Ok. These are my problems.
I need to user regular expressions to filet out everything except for letters and then I need to encase the found words within a $word tag.
With this str = str.replaceAll(pattern, "$0");.
right now I am filtering all of the right elements (punctuation, numbers etc) but its encasing every letter within each word in an a tag not the word. so how do I use the regular expression to group the letters to a word?
from "(a tag open)t(a close)(a tag open)h(a close)(a tag open)i(a close)(a tag open)s(a close) (a tag open)i(a close)(a tag open)s(a close) (a tag open)w(a close)(a tag open)r(a close)(a tag open)o(a close)(a tag open)n(a close)(a tag open)g(a close)";
to :
"(a tag open)This(a close) (a tag open)is(a close) (a tag open)right(a close)";
then I'm making them clickable and I need to catch the click event and get the position on screen on the clicked word as I want to use the clicked event to make a tool tip show up just below the clicked word. thank you for your help.
public class MainActivity extends Activity {
public String text = "This is just a sentence to test you. 23 this is another number23!g?";
public TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = explode(text);
tv = (TextView) findViewById(R.id.tv1);
tv.setLinksClickable(true);
tv.setMovementMethod(LinkMovementMethod.getInstance());
Spanned article = Html.fromHtml(text, null, null);
setHTML(article);
}
public void setHTML(Spanned html) {
SpannableString message = new SpannableString(html.toString());
Object[] spans = html.getSpans(0, html.length(), Object.class);
for (Object span : spans) {
int start = html.getSpanStart(span);
int end = html.getSpanEnd(span);
int flags = html.getSpanFlags(span);
if (span instanceof URLSpan) {
URLSpan urlSpan = (URLSpan) span;
span = new CallbackSpan(urlSpan.getURL());
}
message.setSpan(span, start, end, flags);
}
tv.setText(message);
}
public String explode(String str){
String pattern = "([a-zA-Z])";
str = str.replaceAll(pattern, "$0");
return str;
}
private final class CallbackSpan extends ClickableSpan {
private String m_data;
private String url_main;
public CallbackSpan(String url) {
m_data = url.substring(0);
url_main = url;
}
public void onClick(View view) {
TextView item = (TextView)findViewById(R.id.tv2);
item.setText(url_main + " was clicked.");
Log.d("item", url_main);
}
}
}
Latest code ,pls see link form github
message.setSpan(span, start, end, flags);
You need remove origin span before set new span.
Please see below
The onClick() of ClickableSpan is not working for URLSpan?
EDIT
You can capture any span click event by extends LinkMovementMethod
import android.os.Handler;
import android.os.Message;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.LinkMovementMethod;
import android.text.method.MovementMethod;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.widget.TextView;
import java.lang.ref.WeakReference;
public class LinkMovementMethodExt extends LinkMovementMethod {
public static final int LinkMovementMethod_Down = 1001;
public static final int LinkMovementMethod_Up = 2002;
private static LinkMovementMethod sInstance;
private Class mSpanClass = null;
private WeakReference<Handler> mWeakReference = null;
public static MovementMethod getInstance(Handler handler, Class spanClass) {
if (sInstance == null) {
sInstance = new LinkMovementMethodExt();
((LinkMovementMethodExt) sInstance).mWeakReference = new WeakReference<>(handler);
((LinkMovementMethodExt) sInstance).mSpanClass = spanClass;
}
return sInstance;
}
#Override
public boolean onTouchEvent(TextView widget, Spannable buffer,
MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
/**
* get you interest span
*/
Object[] spans = buffer.getSpans(off, off, mSpanClass);
if (spans.length != 0) {
if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer, buffer.getSpanStart(spans[0]), buffer.getSpanEnd(spans[0]));
MessageSpan obj = new MessageSpan();
obj.setObj(spans);
obj.setView(widget);
Handler handler = mWeakReference.get();
if (handler != null) {
Message message = handler.obtainMessage();
message.obj = obj;
message.what = LinkMovementMethod_Down;
message.sendToTarget();
return true;
}
return false;
} else if (action == MotionEvent.ACTION_UP) {
Handler handler = mWeakReference.get();
if (handler != null) {
MessageSpan obj = new MessageSpan();
obj.setView(widget);
Message message = handler.obtainMessage();
message.obj = obj;
message.what = LinkMovementMethod_Up;
message.sendToTarget();
return true;
}
return false;
}
}
}
return super.onTouchEvent(widget, buffer, event);
}
public boolean canSelectArbitrarily() {
return true;
}
public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode,
KeyEvent event) {
return false;
}
textView.setMovementMethod(LinkMovementMethodExt.getInstance());
Edit for "android developer"
It is better way to add Handler property for LinkMovementMethodExt class.
You can capture all Spanned which are delivered as Message object.
Snip code in onTouchEvent method:
Message message = Handler.obtainMessage();
message.obj = buffer.getSpans(off, off, Spanned.class);//get all spanned
message.what = 111;//which value ,it is up to you
message.sendToTarget(); //send message to you target handler
You can handler expected spanned in you handler class. May be it is flexible way to handle .
Hope to help you.
Above textview text is <a href='/a'>aaaa</a>123456<a href='/b'>bbbb</b>7890
I understand you requirement : Click 'aaaa',you want get its href value '/a', click 'bbbb',get its href '/b'; Do not trigger default action which is opened in web browser.
If my understand is right, you can do like this:
Set LinkMovementMethod for textview, etc:textview.setMovementMethod(LinkMovementMethodExt.getInstance(handler, URLSpan.class));
Get interest span, here is URLSpan.
In you handler handleMessage method, you can do like this:
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
int what = msg.what;
if (what == 100) {
Object[] spans = (Object[])msg.obj;
for (Object span : spans) {
if (span instanceof URLSpan) {
System.out.println(((URLSpan) span).getURL());
}
}
}
};
};
Download demo code
MainActivity has color property which you can assign which color value as you like.
How to do?
Step1, get current click span.
Step2, set BackgroundColorSpan for current click span
Assuming You want click individual words on the textview?. I din't understand the converts all letters to words in your comment.
The below can be used to click on individual works and it is displayed in a toast.
public class MainActivity extends Activity {
TextView _tv;
String[] each;
SpannableString ss1;
Button b;
EditText et;
String s;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b= (Button) findViewById(R.id.button1);
et = (EditText) findViewById(R.id.ed);
_tv = (TextView) findViewById( R.id.tv );
b.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
s=et.getText().toString();
_tv.setText("");
for(int i=0;i<s.length();i++)
{
each = s.split("\\s+");
}
for(int i=0;i<each.length;i++)
{
System.out.println("................"+each[i]);
ss1= new SpannableString(each[i]);
//StyleSpan boldSpan = new StyleSpan( Typeface.BOLD );
//spannable.setSpan( boldSpan, 41, 52, Spannable.SPAN_INCLUSIVE_INCLUSIVE );
ss1.setSpan(new MyClickableSpan(each[i]), 0, ss1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
_tv.append(ss1);
_tv.append(" ");
}
_tv.setMovementMethod(LinkMovementMethod.getInstance());
}
});
}
class MyClickableSpan extends ClickableSpan{
String clicked;
public MyClickableSpan(String string) {
// TODO Auto-generated constructor stub
clicked =string;
}
//clickable span
public void onClick(View textView) {
//do something
Toast.makeText(MainActivity.this,clicked ,
Toast.LENGTH_SHORT).show();
}
#Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Color.BLACK);//set text color
ds.setUnderlineText(false); // set to false to remove underline
}
}
}

How to handle link click events in a textView

I am using Jsoup to parse the a website, formatting it with Html.fromHtml()and displaying the formatted text in a textview.
Also, I'm using LinkMoveMentmethod.getInstance to make the links in the textview clickable.
When the links are clicked they fired up a chooser to choose browsers.
Please, how can I override this default behaviour.
For example, I would want to pass the clicked url to my own activity and use Jsoup to parse it also.
CODE
TextView pageContent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page_details);
getWindow().getDecorView().setBackgroundColor(Color.WHITE);
pageContent = (TextView) findViewById(R.id.dpage_content);
}
....
private void parseHtml(String response) {
Log.d(TAG, "parsinghtml");
Document document = Jsoup.parse(response);
page_content = document.select("div.page-content").first().html();
Spanned spanned = Html.fromHtml(page_content, new UILImageGetter(pageContent, this), null );
}
You need to create your custom class which extends LinkMovementMethod.
public class LinkClickHandler extends LinkMovementMethod{
private static LinkClickHandler sInstance;
public static LinkClickHandler getInstance() {
if (sInstance == null)
sInstance = new LinkClickHandler();
return sInstance;
}
#Override
public boolean onTouchEvent(TextView widget,
Spannable buffer, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP) {
//Implement your code for handling the click.
}
return super.onTouchEvent(widget, buffer, event);
}
}
To use this, change LinkMovementMethod.getInstance to LinkClickHandler.getInstance
You can use clickable span
ClickableSpan cs = new ClickableSpan() {
#Override
public void onClick(View v) {
Log.d("main", "textview clicked");
Toast.makeText(Main.this, "textview clicked",Toast.LENGTH_SHORT).show();
} };
// set the "test " spannable.
span.setSpan(cs, 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(span);
tv.setMovementMethod(LinkMovementMethod.getInstance());

Get the value of link text when clicked in a textview in android

I have a TextView. I have added custom links like "#abc", "#android" by matching some regex pattern. The links are displaying properly. However I am not getting a way to extract the text of the link which is clicked. I am using SpannableString to setText to the textview. I then set spans using my custom ClickableSpan. It works fine. Plus I can also catch the onclick event. But the onClick() method has a View paramter. If I call getText() on the View (ofcourse after typecasting it to TextView), it returns the entire text.
I searched a lot but always found ways to add links and catch the event, but none told about getting the text of the link.
This is the code I am using to add links and recieve onclick. I got the code from one of the SO threads..
Pattern pattern = Pattern.compile("#[\\w]+");
Matcher matcher = pattern.matcher(tv.getText());//tv is my TextView
while (matcher.find()) {
int x = matcher.start();
int y = matcher.end();
final android.text.SpannableString f = new android.text.SpannableString(
tv.getText());
f.setSpan(new InternalURLSpan(new View.OnClickListener() {
public void onClick(View v) {
showDialog(1);
}
}), x, y, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(f);
tv.setLinkTextColor(Color.rgb(19, 111, 154));
tv.setLinksClickable(true);
Here is the InternalURLSpan:
class InternalURLSpan extends android.text.style.ClickableSpan {
View.OnClickListener mListener;
public InternalURLSpan(View.OnClickListener listener) {
mListener = listener;
}
#Override
public void onClick(View widget) {
mListener.onClick(widget);
TextView tv = (TextView) widget;
System.out.println("tv.gettext() :: " + tv.getText());
Toast.makeText(MyActivity.this,tv.getText(),
Toast.LENGTH_SHORT).show();
}
}
Is it possible to get the text of the link clicked?
If not, is there a way of associating some data to a particular link and knowing which link gets clicked?
Any pointers.
Thanks
The solution goes like this -
Call setLinks() with you textview and the text to be added.
setLinks(textView, text);
setLinks() function is as -
void setLinks(TextView tv, String text) {
String[] linkPatterns = {
"([Hh][tT][tT][pP][sS]?:\\/\\/[^ ,'\">\\]\\)]*[^\\. ,'\">\\]\\)])",
"#[\\w]+", "#[\\w]+" };
for (String str : linkPatterns) {
Pattern pattern = Pattern.compile(str);
Matcher matcher = pattern.matcher(tv.getText());
while (matcher.find()) {
int x = matcher.start();
int y = matcher.end();
final android.text.SpannableString f = new android.text.SpannableString(
tv.getText());
InternalURLSpan span = new InternalURLSpan();
span.text = text.substring(x, y);
f.setSpan(span, x, y,
android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(f);
// tv.setOnLongClickListener(span.l);
}
}
tv.setLinkTextColor(Color.BLUE);
tv.setLinksClickable(true);
tv.setMovementMethod(LinkMovementMethod.getInstance());
tv.setFocusable(false);
}
and the InternalURLSpan class goes like this -
class InternalURLSpan extends android.text.style.ClickableSpan {
public String text;
#Override
public void onClick(View widget) {
handleLinkClicked(text);
}
}
handleLinkClicked() is as -
public void handleLinkClicked(String value) {
if (value.startsWith("http")) { // handle http links
} else if (value.startsWith("#")) { // handle #links
} else if (value.startsWith("#")) { // handle #links
}
}
Here is a pretty simple solution I found to get the value of the link inside the TextView when the user clicks on it. In this case I'm using phone numbers and it works like a charm.
myTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(myTextView.getSelectionStart()== -1 &&
myTextView.getSelectionEnd() == -1){
Toast.makeText(getApplicationContext(), "You clicked outside the link",
Toast.LENGTH_SHORT).show();
}
else {
int start = myTextView.getSelectionStart();
int end = myTextView.getSelectionEnd();
String selected = myTextView.getText().toString().substring(start, end);
Toast.makeText(getApplicationContext(),
"Clicked: " + selected,
Toast.LENGTH_SHORT).show();
}
}
});
Hope it helps.
Use
android:linksClickable="true"
android:autoLink="web"
textView.setMovementMethod(LinkMovementMethod.getInstance())

android dev how to underline and change color of word in string like a link color

I have a app that gets a string from a database and it sets to a label. Now i want that label to underline one word such as "This word should be underlined." and i want to be able to click on that underline word and get its value. So do i set it up before i send it to the database or after. Thanks for any help. I tried code below and each line is highlighted because of the for loop. please help
SpannableStringBuilder builder = new SpannableStringBuilder();
for(int i=0;i<ListClass.getLatestActivity().size();i++){
String myString = ListClass.getLatestActivity().get(i);
builder.append(myString);
String substringThatShouldBeClickable = myString.substring(0,myString.indexOf(' ')).trim();
MySpan span = new MySpan(substringThatShouldBeClickable);
span.setOnMySpanClickListener(mySpanOnClickListener);
int start = 0;
int end = builder.length();
builder.setSpan(span, start, end, 0);
builder.append("\n" + "\n") ;
}
RAInfo.setText(builder);
RAInfo.setMovementMethod(LinkMovementMethod.getInstance());
Ok, so there's a few things you'll need to do. They way to accomplish this is by using a span inside of the TextView.
First you'll need a class that extends ClickableSpan:
public class MySpan extends ClickableSpan {
public interface OnMySpanClickListener {
public void onMySpanClick(String tag);
}
private final String myData;
private OnMySpanClickListener mOnMySpanClickListener;
public MySpan(String tag) {
super();
if (tag == null) {
throw new NullPointerException();
}
myData = tag;
}
#Override
public void onClick(View widget) {
if (mOnMySpanClickListener != null) {
mOnMySpanClickListener.onMySpanClick(myData);
}
}
public OnMySpanClickListener getOnMySpanClickListener() {
return mOnMySpanClickListener;
}
public void setOnMySpanClickListener(OnMySpanClickListener onMySpanClickListener) {
mOnMySpanClickListener = onMySpanClickListener;
}
}
In your Activity, you'll set the text of the TextView like this:
String myString = getFromDatabase();
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(myString);
//You'll need to call the constructor for MySpan with only the value of the part
//of the string that you want to work with ("Bob" in the example), however you
//determine that.
String substringThatShouldBeClickable = getMySubstring(myString); //"Bob"
MySpan span = new MySpan(substringThatShouldBeClickable);
span.setOnMySpanClickListener(mySpanOnClickListener);
//start and end control the range of characters in the string that are clickable,
//so modify this part so it only underlines the characters you want clickable
int start = 0;
int end = bulider.length();
builder.setSpan(span, start, end, 0);
label.setText(builder);
label.setMovementMethod(LinkMovementMethod.getInstance());
Finally, you'll need a handler for the click events on the span:
MySpan.OnMySpanClickListener mySpanOnClickListener = new MySpan.OnMySpanClickListener() {
public void onMySpanClick(String tag) {
//Here is where you'll do your work with the value in the String "tag"
}
};
Hope this helps.

Categories

Resources