在当前光标位置获取EditText中的单词

7

我是一名新手安卓开发者。我在edittext中添加了一个上下文菜单。我希望在长按时获取光标下的单词。

我可以通过以下代码获取所选文本。

@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 包含一些文本,例如 "Some text. Some more text"。当用户点击 "more" 时,光标将在单词 "more" 的某个位置。当用户长按该单词时,我想获取单词 "more" 和光标下的其他单词。


备选方案:使用BreakIterator.getWordInstance()。请参见https://dev59.com/25_ha4cB1Zd3GeqPtx4g - Suragch
5个回答

8
有更好、更简单的解决方案:在安卓中使用模式。
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
}

需要初始化currentWord。currentWord = ""; 除此之外,这是一个非常好的解决方案。 - Chad Bingham
目前最灵活的解决方案。但是我使用"\w+(-\w+)*"作为正则表达式,因为有包含连字符的单词。例如:按次付费。 - ka3ak

6
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);

这不会选择除空格以外的其他分隔符分开的单词。 - Suragch

3

我认为在这里使用BreakIterator是更优秀的解决方案。它避免了需要循环整个字符串并自己进行模式匹配。它还可以找到单词边界,不仅限于简单的空格字符(逗号、句号等)。

// 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);

如果您想在长按时进行操作,只需将以下内容放入您的GestureDetectoronLongPress方法中即可。

另请参阅


3
请尝试使用以下代码,它已经进行了优化。如果您有更多的规格要求,请告诉我。
//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();

这里只是一个简单的注释,可能不够清晰,对于任何想要处理这种情况的人:如果我的光标位置在第一个单词上 --> 意味着lastSpaceIndex将会是-1,不用担心,因为当我们截取字符串时,我们会在lastSpaceIndex上加上+1 --> 这意味着它将变成0,并且它是字符串的第一个索引。 - Mina Samir

0

@Ali 感谢您提供的解决方案。

这里是一个优化的变体,如果找到单词,它会进行中断

此解决方案不会创建Spannable,因为没有必要找到该单词。

@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;
}

示例:获取当前光标位置的单词:

String text = editText.getText().toString();
int cursorPosition = editText.getSelectionStart();

String wordAtCursorPosition = getWordAtIndex(text, cursorPosition);

如果您想找到所有相关字符(包括标点符号),请使用以下替代方法:

// S = non-whitespace character: [^\s]
final Pattern pattern = Pattern.compile("\\S+");

Java 正则表达式文档(regular-expression):https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接