编辑框行间距和光标位置问题

3

我正在尝试创建一个带有良好间距的Edittext。它可以工作,但是光标位置不正确。请看下面的图片。正如您所见,光标处于两行之间。

这是Edittext代码:

     <EditText
            android:id="@+id/editText1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            android:fadingEdge="vertical"
            android:gravity="left|center_vertical"
            android:lineSpacingExtra="10dp"
            android:lineSpacingMultiplier="2"
            android:padding="18dp"
            android:scrollbars="vertical"
            android:textSize="22sp" >

            <requestFocus />
        </EditText>

enter image description here


android:gravity="left" 移除 center_vertical。 - Subburaj
@RahulGupta,你得到了正确的工作解决方案吗?请在SO上分享。 - eRaisedToX
2个回答

1
如果你在使用textCursorDrawablelineSpacingExtra时,会遇到另一个问题:当你的应用程序在Lollipop以上的版本运行时,由于最后一行的行高不会改变,如果在自定义的textCursorDrawable中定义了负底部填充,则光标会在最后一行缩小,如下图所示:

enter image description here

为了达到更惊人的效果,我将lineSpacingExtra设置为8dp,并且我的自定义textCursorDrawable的一部分是<padding android:bottom="-8dp"/>。因此,您可以看到小光标出现在最后一行。
当然,我们不喜欢这个。我在互联网上搜索了数小时和数天,但没有任何页面能够帮助我。但是,如果您看到了这个答案,就不必为此担心,因为我已经用我的方式解决了这个问题,虽然有点hacky,但据我所知很好用。
我们问题的根本原因在于我们为textCursorDrawable设置了底部填充,并将其缩短了所有行。假设文本大小为12dp,则原始行高也为12dp(只是为了方便)。在我们定义了lineSpacingExtra="8dp"之后,行高将增加到20dp。如果我们不对textCursorDrawable进行任何操作,则光标高度现在也将变为20dp,显然比文本大小长,因此我们缩短它,通过在自定义的textCursorDrawable形状XML文件中定义<padding android:bottom="-8dp"/>来剪切底部的8dp。然而,在Lollipop以上版本中,lineSpacingExtra会忽略最后一行,因此该行的行高仍保持在12dp。如果我们不使用自定义光标,则最后一行的光标也是如此。然后我们削减了那个8dp,现在我们看到一个4dp的光标,这是错误的,正确的操作是停止在自定义textCursorDrawable中设置-8dp的底部填充。
因此解决方案是:对于普通行和最后一行使用不同的textCursorDrawable,充分尊重特殊的一行。
那么,什么时候应该更改textCursorDrawable呢?我的答案是:当用户单击EditText的最后一行时。这很合理,因为光标只能在此操作之后出现(如果用户在此之后点击“enter”可能不是最后一个操作,但这并不影响我们的解决方案)。
下一步是监听用户在最后一行上的单击。我的解决方案很简单:
mEditText.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            EditText et = (EditText) v;
            // lineSpacingExtra's unit is px.
            int lastLineHeight = (int) (et.getLineHeight() - et.getLineSpacingExtra());
            if (et.getHeight() - event.getY() <= lastLineHeight) {
                setTextCursorDrawable(et, lastLineCursorRes);
            } else {
                setTextCursorDrawable(et, normalCursorRes);
            }
            return true;
        }
        return false;
    }
});

以下是不太优雅的(但我们必须这样做)setTextCursorDrawable实现:

public void setTextCursorDrawable(EditText et, @DrawableRes int res) {
    try {
        Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
        f.setAccessible(true);
        f.set(et, res);
    } catch (Exception ignored) {}
}

最后,lastLineCursorRes 的特殊部分:

<padding android:bottom="0dp"/>

好的,就是这样。请注意,我在尝试此解决方案并发现它有效后立即编写了此答案,这意味着我没有仔细检查它。如果您在使用此解决方案时遇到任何问题,请留言评论。

参考资料

要了解为什么在 TextView 及其子类的最后一行中忽略 lineSpacingExtra/Multiplier,请参阅:How LineSpace Affects StaticLayout Height in One Line TextAndroid TextView 行间距解析(in Chinese)StaticLayout源码解析(in Chinese)


1

你需要使用android:textCursorDrawable="@drawable/name_of_your_drawable"来设置自己的光标可绘制对象,并在padding中设置android:bottom="-20sp"(或文本大小)的值。就像这个例子一样。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.androisxxxsxsxd.com/apk/res/android"
    android:shape="rectangle" >
    <size 
        android:width="2dip" />
    <solid
        android:color="@color/red" />
    <padding 
        android:top="2sp"
        android:bottom="-20sp" />
</shape>

myxml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <EditText
    android:id="@+id/edittext"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    android:paddingTop="18dp"
    android:gravity="left|center_vertical"
    android:lineSpacingExtra="20dp"
    android:textCursorDrawable="@drawable/d"
    android:text="test" 
    />

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