select a word on a tap in TextView/EditText
12,206
UPDATE: Another better approach is to use BreakIterator
:
private void init() {
String definition = "Clickable words in text view ".trim();
TextView definitionView = (TextView) findViewById(R.id.text);
definitionView.setMovementMethod(LinkMovementMethod.getInstance());
definitionView.setText(definition, BufferType.SPANNABLE);
Spannable spans = (Spannable) definitionView.getText();
BreakIterator iterator = BreakIterator.getWordInstance(Locale.US);
iterator.setText(definition);
int start = iterator.first();
for (int end = iterator.next(); end != BreakIterator.DONE; start = end, end = iterator
.next()) {
String possibleWord = definition.substring(start, end);
if (Character.isLetterOrDigit(possibleWord.charAt(0))) {
ClickableSpan clickSpan = getClickableSpan(possibleWord);
spans.setSpan(clickSpan, start, end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
private ClickableSpan getClickableSpan(final String word) {
return new ClickableSpan() {
final String mWord;
{
mWord = word;
}
@Override
public void onClick(View widget) {
Log.d("tapped on:", mWord);
Toast.makeText(widget.getContext(), mWord, Toast.LENGTH_SHORT)
.show();
}
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
}
};
}
OLD ANSWER
I wanted to handle click in my own Activity. I solved it by following code:
private void init(){
String definition = "Clickable words in text view ".trim();
TextView definitionView = (TextView) findViewById(R.id.definition);
definitionView.setMovementMethod(LinkMovementMethod.getInstance());
definitionView.setText(definition, BufferType.SPANNABLE);
Spannable spans = (Spannable) definitionView.getText();
Integer[] indices = getIndices(
definitionView.getText().toString(), ' ');
int start = 0;
int end = 0;
// to cater last/only word loop will run equal to the length of indices.length
for (int i = 0; i <= indices.length; i++) {
ClickableSpan clickSpan = getClickableSpan();
// to cater last/only word
end = (i < indices.length ? indices[i] : spans.length());
spans.setSpan(clickSpan, start, end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
start = end + 1;
}
}
private ClickableSpan getClickableSpan(){
return new ClickableSpan() {
@Override
public void onClick(View widget) {
TextView tv = (TextView) widget;
String s = tv
.getText()
.subSequence(tv.getSelectionStart(),
tv.getSelectionEnd()).toString();
Log.d("tapped on:", s);
}
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
}
};
}
public static Integer[] getIndices(String s, char c) {
int pos = s.indexOf(c, 0);
List<Integer> indices = new ArrayList<Integer>();
while (pos != -1) {
indices.add(pos);
pos = s.indexOf(c, pos + 1);
}
return (Integer[]) indices.toArray(new Integer[0]);
}
Author by
M-Wajeeh
https://www.linkedin.com/in/muhammadwajeeh [email protected]
Updated on June 17, 2022Comments
-
M-Wajeeh almost 2 years
How to select a word on a tap in
TextView
/EditText
in android. I have some text in aTextView
/EditText
and when user taps on a word, I want that word to be selected and after that when I call getSelectedText() like method, it should return me the selected word. Any Help would be appreciated.My goal is to perform some action when user taps on a particular word in
TextView
/EditText
. -
M-Wajeeh over 12 yearsExcellent. But I wanted to handle click event via listener, not via Intents :)
-
Deepak G M almost 12 yearsThis is the best answer if you are looking at listeners solution and not intents. Not all problems are linked with a URL or a schema. In my case, I was looking at a simple solution to get to know which word was tapped in a textview. There was no good solution till I saw this. This solution just works perfectly. It does the same thing as to what textview clickable does but the best part is we are in control to take relevant action. I did one change though to the above code. With the above code, all words appear as links but I did not want that. So just commented the super.updateDrawState.
-
Hardik Joshi about 11 yearsThank you so much i working on this from last 2 days and finally I solve it by using your code. Thank you again.
-
Manu over 10 yearsThank you M-WaJeEh. Worked like a charm. And also thanks Deepak for that added bit which I wanted.
-
KK_07k11A0585 almost 9 years@M-WaJeEh I have integrated the code provided by you, but I do not want the underline on every word. How can I remove this ? Please let me know
-
KK_07k11A0585 almost 9 years@M-WajeEh Also, I want to give click event on the lines and I am using BreakIterator.getLineInstance() but it is not working. Please suggest me an example
-
M-Wajeeh almost 9 years@KK_07k11A0585 don't call
super.updateDrawState(ds);
to avoid underline effect andBreakIterator.getLineInstance()
will work if you put "\n" in your strings, I don't think it will detect visual line breaks byTextView
. -
KK_07k11A0585 almost 9 years@M-WaJeEh Thanks for your answer, my requirement is I have a textview and when user tap on it, I need to change the background color of the line on which he has tapped. Can I achieve this using getLineInstance ?? Please let me know
-
M-Wajeeh almost 9 years@KK_07k11A0585 No you can't use
getLineInstance()
, combine stackoverflow.com/a/6726707/1112882 with stackoverflow.com/a/6273546/1112882 to achieve what you are looking for. -
Carlos Botero almost 6 yearsTo: M-Waje. public void updateDrawState(TextPaint ds) { ds.setColor(Color.WHITE); // Choose color ds.setUnderlineText(false); } // Saludos