如何在安卓中更改多行编辑文本中的光标位置?



首先,我已经阅读了有关此事的其他问题,但我正在尝试不同的东西。

我有一个多行编辑文本,其中包含以下 XML:

<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="@color/textBodyColor"
android:id="@+id/editScriptET"
android:isScrollContainer="true"
android:scrollbars="vertical"
android:textSize="@dimen/font20"
android:hint="@string/details"
android:fontFamily="@font/courier_prime"
android:inputType="textMultiLine"
/>

我要做的是在单击菜单项时将光标设置在行的中心或行的左侧(在该多行 EditText 中(。因此,当我单击菜单项时,我希望光标在 EditText 中当前行的中心移动。当按下另一个菜单项时,我需要光标转到当前行的左侧。 (所有菜单项始终显示在工具栏上。

有没有办法做到这一点?

我尝试使用scriptET.setGravity(Gravity.CENTER);(其中scriptET是对我的 EditText 的引用(,但没有任何反应。

编辑:使用评论中收到的建议,我设法将光标设置为左侧,Selection.moveToLeftEdge(scriptET.getText(), scriptET.getLayout());.使用一些 Toasts 消息,我注意到getLayout()方法给出 null,但在单击时光标仍在当前行的左侧移动。

此外,当行为空时,无法将光标移动到"逻辑"中心,我真的需要这样做。

任何建议都非常感谢!

有一个android.text.Selection类,它允许您在 EditText 中移动光标:

要将光标移动到行的左侧,请使用Selection.moveToLeftEdge(edt.getText(), edt.getLayout())。还有一种方法可以将光标移动到当前行的右侧。

将光标移动到行的中心有点复杂。首先,您必须确定线条的"中心"是什么意思。例如,如果我们有以下行:

WWWWWWWWWWWWWWWWWWWWWWlll

它由 25 个大写 Ws 和 25 个大写 L 组成。在这一行中,中心是在 Ws 和 L 的交界处(在 pos 25 处(还是在 Ws 块内的某个地方?我们称前者为"逻辑"中心,后者称为"视觉"中心。

下面是将光标移动到逻辑中心的方法:

public void moveToLogicalLineCenter(EditText edt) {
Spannable text = edt.getText();
Layout layout = edt.getLayout();
// Find the index of the line that cursor is currently on.
int pos = Selection.getSelectionStart(text);
int line = layout.getLineForOffset(pos);
// Find the start pos and end pos of that line.
int lineStart = layout.getLineStart(line);
int lineEnd = layout.getLineEnd(line);
// Calculate center pos and set selection.
int lineCenter = Math.round((lineEnd + lineStart) / 2f);
Selection.setSelection(text, lineCenter);
}

下面是将光标移动到视觉中心的方法:

public void moveToVisualLineCenter(EditText edt) {
Spannable text = edt.getText();
Layout layout = edt.getLayout();
// Find the index of the line that cursor is currently on.
int pos = Selection.getSelectionEnd(text);
int line = layout.getLineForOffset(pos);
// Find the start pos and end pos of that line, and its text.
int lineStart = layout.getLineStart(line);
int lineEnd = layout.getLineEnd(line);
CharSequence lineText = text.subSequence(lineStart, lineEnd);
// Measure substrings of the line text of increasing lengths until we find the closest
// to the EditText's center position.
int centerX = edt.getMeasuredWidth() / 2 - edt.getPaddingLeft();
TextPaint paint = edt.getPaint();
float lastWidth = 0;
for (int i = 1; i < lineText.length(); i++) {
float width = paint.measureText(lineText, 0, i);
if (width >= centerX) {
// We're past the visual center.
if (centerX - lastWidth < width - centerX) {
// Turns out the last pos was closest, not this one.
edt.setSelection(lineStart + i - 1);
} else {
// This pos is closest to the center.
edt.setSelection(lineStart + i);
}
return;
}
lastWidth = width;
}
if (lineText.length() != 0) {
// Line doesn't reach center, select line end.
edt.setSelection(lineEnd);
}  // Otherwise, line was empty, start of the line is already selected.
}

此方法使用TextPaint来测量文本,以找到最接近 EditText 可视中心的位置。如果行未到达中心,光标将转到行的末尾。理想情况下,您需要在此处进行二叉搜索而不是线性搜索,以快速找到最近的位置,因为TextPaint.measureText是一项可能昂贵的操作。例如,如果您打算使用包含数千个字符的行,则可能是最好的。

我希望这能回答您的问题,否则发表评论。

只需设置文本对齐属性;

最新更新