I am new to android programing. I added a context menu to edittext. I wish I can get word under cursor on long press. Help Please. I can get selected text by following code.
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
EditText edittext = (EditText)findViewById(R.id.editText1);
menu.setHeaderTitle(edittext.getText().toString().substring(edittext.getSelectionStart(), edittext.getSelectionEnd()));
menu.add("Copy");
}
edittext have some text e.g "Some text. Some more text". User clicked on "more" so the cursor will be in some where in the word "more". I want when user long press the word I can get the word "more" and so on other words under the cursor.
EditText et = (EditText) findViewById(R.id.xx);
int startSelection = et.getSelectionStart();
String selectedWord = "";
int length = 0;
for(String currentWord : et.getText().toString().split(" ")) {
System.out.println(currentWord);
length = length + currentWord.length() + 1;
if(length > startSelection) {
selectedWord = currentWord;
break;
}
}
System.out.println("Selected word is: " + selectedWord);
There is better and simpler solution : using pattern in android
public String getCurrentWord(EditText editText) {
Spannable textSpan = editText.getText();
final int selection = editText.getSelectionStart();
final Pattern pattern = Pattern.compile("\\w+");
final Matcher matcher = pattern.matcher(textSpan);
int start = 0;
int end = 0;
String currentWord = "";
while (matcher.find()) {
start = matcher.start();
end = matcher.end();
if (start <= selection && selection <= end) {
currentWord = textSpan.subSequence(start, end).toString();
break;
}
}
return currentWord; // This is current word
}
Please try following code as it is optimized. Let me know if you has more specification.
//String str = editTextView.getText().toString(); //suppose edittext has "Hello World!"
int selectionStart = editTextView.getSelectionStart(); // Suppose cursor is at 2 position
int lastSpaceIndex = str.lastIndexOf(" ", selectionStart - 1);
int indexOf = str.indexOf(" ", lastSpaceIndex + 1);
String searchToken = str.substring(lastSpaceIndex + 1, indexOf == -1 ? str.length() : indexOf);
Toast.makeText(this, "Current word is :" + searchToken, Toast.LENGTH_SHORT).show();
I believe that a BreakIterator
is the superior solution here. It avoids having to loop over the entire string and do the pattern matching yourself. It also finds word boundaries besides just a simple space character (commas, periods, etc.).
// assuming that only the cursor is showing, no selected range
int cursorPosition = editText.getSelectionStart();
// initialize the BreakIterator
BreakIterator iterator = BreakIterator.getWordInstance();
iterator.setText(editText.getText().toString());
// find the word boundaries before and after the cursor position
int wordStart;
if (iterator.isBoundary(cursorPosition)) {
wordStart = cursorPosition;
} else {
wordStart = iterator.preceding(cursorPosition);
}
int wordEnd = iterator.following(cursorPosition);
// get the word
CharSequence word = editText.getText().subSequence(wordStart, wordEnd);
If you want to get it on a long press then just put this in the onLongPress
method of your GestureDetector
.
See also
- How does BreakIterator work in Android?
@Ali Thank you for providing your solution.
Here is an optimized variant, which does break if the word has been found.
This solution does not create a Spannable, because it is not needed to find the word.
@NonNull
public static String getWordAtIndex(@NonNull String text, @IntRange(from = 0) int index) {
String wordAtIndex = "";
// w = word character: [a-zA-Z_0-9]
final Pattern pattern = Pattern.compile("\\w+");
final Matcher matcher = pattern.matcher(text);
int startIndex;
int endIndex;
while (matcher.find()) {
startIndex = matcher.start();
endIndex = matcher.end();
if ((startIndex <= index) && (index <= endIndex)) {
wordAtIndex = text.subSequence(startIndex, endIndex).toString();
break;
}
}
return wordAtIndex;
}
Example: Get the word at the current cursor position:
String text = editText.getText().toString();
int cursorPosition = editText.getSelectionStart();
String wordAtCursorPosition = getWordAtIndex(text, cursorPosition);
Use this instead if you want to find all connected characters (including punctuation):
// S = non-whitespace character: [^\s]
final Pattern pattern = Pattern.compile("\\S+");
Java regex documentation (regular-expression): https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html