How to Click or Tap on a Textview Text on Different Words

How to click or tap on a TextView text on different words?

I finally figured it out how to have multiple clickable parts in a TextView.
It is important that they all have their own ClickableSpan! That is where I went wrong the first time testing it. If they have the same ClickableSpan instance, only the last set span is remembered.

I created a String with the required clickable area's surrounded by "[" and "]".

String sentence = "this is [part 1] and [here another] and [another one]";

and here is the set TextView, the setMovementMehthod is also mandatory:

textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(addClickablePart(sentence), BufferType.SPANNABLE);

I have created this function, which will handle the creation of the clickable area's:

private SpannableStringBuilder addClickablePart(String str) {
SpannableStringBuilder ssb = new SpannableStringBuilder(str);

int idx1 = str.indexOf("[");
int idx2 = 0;
while (idx1 != -1) {
idx2 = str.indexOf("]", idx1) + 1;

final String clickString = str.substring(idx1, idx2);
ssb.setSpan(new ClickableSpan() {

@Override
public void onClick(View widget) {
Toast.makeText(getView().getContext(), clickString,
Toast.LENGTH_SHORT).show();
}
}, idx1, idx2, 0);
idx1 = str.indexOf("[", idx2);
}

return ssb;
}

select a word on a tap in TextView/EditText

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

How to set multiple on click listeners on different words of textview?

Spannable String are used in Android to highlight the particular portion of text with different click event in a Single TextView.

You can check #SO Demo for this

  1. How to set the part of the text view is clickable

  2. Android: ClickableSpan in clickable TextView

I hope it will helps you .

Extracting words from TextView after click/press on them

Try setting this attribute to your TextView:

android:textIsSelectable="true"

EDIT:

private static final int MENU_ITEM_ID = 0x42;
private TextView targetTextView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

targetTextView = (TextView) findViewById(R.id.target_textview);
targetTextView.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// you can remove the default menu items if you wish
menu.removeItem(android.R.id.selectAll);
menu.removeItem(android.R.id.cut);
menu.removeItem(android.R.id.copy);
return true;
}

@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
/*
* called when the action mode is created. Here you can
* generate action buttons for this action mode.
* */
menu.add(0, MENU_ITEM_ID, 0, "Menu Item").setIcon(android.R.drawable.ic_dialog_alert);
return true;
}

@Override
public void onDestroyActionMode(ActionMode mode) {
// called when the action mode is about to be destroyed
}

@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case MENU_ITEM_ID:
int start = targetTextView.getSelectionStart();
int end = targetTextView.getSelectionEnd();
CharSequence selectedText = targetTextView.getText().subSequence(start, end);
Toast.makeText(MainActivity.this, selectedText, Toast.LENGTH_SHORT).show();
mode.finish();
return true;
default:
break;
}
return false;
}
});
}

How to display each clicked words from TextView

Finally I got the Exact answer for my question

aboutTextView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
mOffset = aboutTextView.getOffsetForPosition(motionEvent.getX(), motionEvent.getY());
// mTxtOffset.setText("" + mOffset);
Toast.makeText(HomeScreen.this, findWordForRightHanded(aboutTextView.getText().toString(), mOffset), Toast.LENGTH_SHORT).show();

}
return false;
}
});

private String findWordForRightHanded(String str, int offset) { // when you touch ' ', this method returns left word.
if (str.length() == offset) {
offset--; // without this code, you will get exception when touching end of the text
}

if (str.charAt(offset) == ' ') {
offset--;
}
int startIndex = offset;
int endIndex = offset;

try {
while (str.charAt(startIndex) != ' ' && str.charAt(startIndex) != '\n') {
startIndex--;
}
} catch (StringIndexOutOfBoundsException e) {
startIndex = 0;
}

try {
while (str.charAt(endIndex) != ' ' && str.charAt(endIndex) != '\n') {
endIndex++;
}
} catch (StringIndexOutOfBoundsException e) {
endIndex = str.length();
}

// without this code, you will get 'here!' instead of 'here'
// if you use only english, just check whether this is alphabet,
// but 'I' use korean, so i use below algorithm to get clean word.
char last = str.charAt(endIndex - 1);
if (last == ',' || last == '.' ||
last == '!' || last == '?' ||
last == ':' || last == ';') {
endIndex--;
}

return str.substring(startIndex, endIndex);
}

How to set the part of the text view is clickable

android.text.style.ClickableSpan can solve your problem.

SpannableString ss = new SpannableString("Android is a Software stack");
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View textView) {
startActivity(new Intent(MyActivity.this, NextActivity.class));
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
};
ss.setSpan(clickableSpan, 22, 27, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

TextView textView = (TextView) findViewById(R.id.hello);
textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setHighlightColor(Color.TRANSPARENT);

In XML:

<TextView 
...
android:textColorLink="@drawable/your_selector"
/>


Related Topics



Leave a reply



Submit