我正在使用软键盘,我需要在IME编辑文本中设置光标位置。
如上图所示,我创建了软键盘,因为我们可以看到在编辑文本和当前光标位置输入了一些文本(由蓝色指示符显示)。
我需要将光标位置设置在当前行的末尾(在我们的情况下,首先在图像中以红色显示的行的末尾)
我尝试使用[{1}}提供的不同功能,我尝试过,
InputConnection
还有一件事,我还需要计算编辑文本中的行数(在我们的例子中是两行)。
答案 0 :(得分:3)
其他一些答案似乎过于复杂或不完整。这是未来访客的一般答案。
如果您对EditText有引用,那么很容易。
设置光标位置
editText.setSelection(index);
设置所选范围
editText.setSelection(startIndex, endIndex);
因为您无法直接访问EditText,因此从IME中获得更多困难。但是,您可以使用InputConnection设置光标位置和选择。
以下答案从InputMethodService
子类中获取这样的输入连接:
InputConnection inputConnection = getCurrentInputConnection();
设置光标位置
inputConnection.setSelection(index, index);
设置所选范围
inputConnection.setSelection(startIndex, endIndex);
将光标移至开始
inputConnection.setSelection(0, 0);
将光标移至末尾
ExtractedText extractedText = inputConnection.getExtractedText(new ExtractedTextRequest(), 0);
if (extractedText == null || extractedText.text == null) return;
int index = extractedText.text.length();
inputConnection.setSelection(index, index);
这种方法不能保证工作,因为如果文本很长,提取的文本将不是EditText中的整个文本。但是,对于大多数情况来说,这很好。另一种选择是使用以下
的组合inputConnection.getTextBeforeCursor(numberOfChars, 0)
inputConnection.getSelectedText(0)
inputConnection.getTextAfterCursor(numberOfChars, 0)
其中numberOfChars
是一个很大的数字。
获取当前光标索引(或选择)
ExtractedText extractedText = inputConnection.getExtractedText(new ExtractedTextRequest(), 0);
int startIndex = extractedText.startOffset + extractedText.selectionStart;
int endIndex = extractedText.startOffset + extractedText.selectionEnd;
如果extractedText
未返回EditText
的全文,则startOffset
会告诉您它从何处被拉出。然后,您可以通过将startOffset
添加到提取的文本的选择开始或结束来获取实际的光标索引。
相对于当前位置移动光标
一旦知道光标的当前位置,就可以轻松移动光标。下面是一个将光标移动到上一个单词开头的示例。
BreakIterator boundary = BreakIterator.getWordInstance();
boundary.setText(extractedText.text.toString());
int preceding = boundary.preceding(extractedText.selectionStart);
int newIndex = (preceding == BreakIterator.DONE) ? selectionStart : preceding;
inputConnection.setSelection(newIndex, newIndex);
请参阅其他BreakIterator
个选项here。
您还可以通过向下发送d-pad事件向左,向右,向上和向下移动。
向左移动
inputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT));
inputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_LEFT));
向右移动
inputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT));
inputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_RIGHT));
向上移动
inputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP));
inputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_UP));
向下移动
inputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN));
inputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_DOWN));
答案 1 :(得分:2)
嗨,各位朋友,谢谢。在两天之前我得到了我的 解决方案,但无法更新我的答案。
为此,我使用了下面的代码,
如果我们使用的api版本大于10,
sendDownUpKeyEvents(0x0000007b);
因为这个方法是在api 11中添加的。
如果我们使用的api版本低于11,
if (getCurrentInputConnection() != null) {
CharSequence textAfter = getCurrentInputConnection().getTextAfterCursor(1024, 0);
if (!TextUtils.isEmpty(textAfter)) {
int newPosition = 1;
while (newPosition < textAfter.length()) {
char chatAt = textAfter.charAt(newPosition);
if (chatAt == '\n' || chatAt == '\r') {
break;
}
newPosition++;
}
if (newPosition > textAfter.length())
newPosition = textAfter.length();
try {
CharSequence textBefore = getCurrentInputConnection().getTextBeforeCursor(Integer.MAX_VALUE, 0);
if (!TextUtils.isEmpty(textBefore)) {
newPosition = newPosition + textBefore.length();
}
getCurrentInputConnection().setSelection(newPosition, newPosition);
} catch (Exception e) {
e.printStackTrace();
}
}
}
答案 2 :(得分:1)
下面是一些可以做你想要的工作代码。
这很简单:
要将光标位置设置为第一行的末尾,我们首先必须获取该行的最后一个文本字符的索引。 EditTexts的布局上有一种方法可以执行此操作。
布局是edittext在内部用于布局文本的内容,它有一个名为 getLineEnd 的方法,它返回一行末尾的文本索引(我们需要从中减去1,否则我们的光标会在下一行的开头结束。)
一旦我们有了设置光标的位置,我们只需使用EditText的 setSelection 方法。
int endOfFirstLine = editText.getLayout().getLineEnd(0)-1;
//set the text selection (cursor postion) to that index
editText.setSelection(endOfFirstLine);
我们也可以通过
轻松获得行数int lineCount = editText.getLineCount();
使用此代码的技巧是,必须在构建EditText的布局后运行它。这意味着如果我们将它放在onCreate或onResume上,它就行不通。行数为0.
因此我们必须在布局传递完成后运行此代码。我们通过向edittext添加布局侦听器,并在完成后运行代码来完成此操作。
editText.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override public void onGlobalLayout() {
}
以下是完整的活动代码:
public class MainActivity extends Activity {
private EditText editText;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.test_edittext);
editText.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override public void onGlobalLayout() {
//this gives us the index of the text at the end of the first line.
int endOfFirstLine = editText.getLayout().getLineEnd(0)-1;
//set the text selection (cursor postion) to that index
editText.setSelection(endOfFirstLine);
//we can get the line count with getLineCount
int lineCount = editText.getLineCount();
Toast.makeText(MainActivity.this, "number of edittext lines: " + lineCount, Toast.LENGTH_LONG).show();
}
});
}
@Override protected void onResume() {
super.onResume();
}
}
答案 3 :(得分:1)
我很遗憾地说你无法通过IME做到这一点。为此,您应该访问EditText的某些方法,但是没有任何可用的API可用,因为textview控件在活动中是另一个进程,而不是您的进程。
您可以获得的所有信息都是您在EditorInfo参数中可以看到的,您可以在一些InputMethodService方法中看到这些信息,例如onStartInput(EditorInfo属性,布尔重启)。可能在未来还包括一些其他方式来访问更多信息,但此时,你可以做的就是你要求的一切,就是用setSelection
InputConnection
方法更改光标位置,但你也不知道第一行末尾的位置是哪一个,所以对你所需的东西不是很有用。