如何在android中改变多行edittext中的光标位置?

问题描述 投票:0回答:2

首先,我已经阅读了关于这个问题的其他问题,但我正在尝试一些不同的东西。

我有一个多行EditText,如下图所示。

<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的引用),但是什么都没有发生。

EDIT: 使用评论中的建议,我设法将光标设置为左边,用 Selection.moveToLeftEdge(scriptET.getText(), scriptET.getLayout());. 通过使用一些Toasts信息,我注意到 getLayout() 方法给出的是null,但点击时光标还是会移动到当前行的左边。

另外,当行为空时,在 "逻辑 "中心移动光标是不可能的,我真的需要这样做。

任何建议都非常感谢!

java android android-edittext cursor-position
2个回答
2
投票

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

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

将光标移动到行的中心是比较复杂的。首先,你必须决定你所说的 "中心 "是什么意思。例如,如果我们有以下一行。

由25个大写字母W和25个小写字母L组成。在这条线中,中心是在Ws和Ls的交界处(位置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 是一个潜在的昂贵操作。例如如果你打算有几千个字符的行,可能是最好的。

我希望这能回答你的问题,否则请留言。


-1
投票

只要设置TextAlignment属性。

© www.soinside.com 2019 - 2024. All rights reserved.