安卓API28以上自定义EditText的行间距不相等

由于之前用的一个便签应用在我换新手机后不兼容了,目前也没发现类似的便签应用,就花了半个月时间研究了下安卓程序开发,真实一把辛酸一把泪,坑的我这个javaer当场死亡。我特么绝壁再也不碰这辣鸡玩意了。

References:

给EditText添加下划线这个功能太常见了,基本上有多行文本编辑的地方都能看到,大多数实现方式就是自定义一个EditText重写onDraw方法自己画线,这里也不例外,然而在我给EditText加下划线的时候发生了这样的事:
baseline.gif

换了多行之后不但线画的不准,偏移了,在一行内输入中英文时甚至会改变行高,我特么直接吐了,这让人还怎么划线。这里不管怎么计算ascent、decent、leading、fontMetrics这些乱七八糟的都没用。然后查了很久才找到问题所在,还得多亏了StackOverflow上的这位兄台,Google官方居然还大言不惭说这是Feature,不是Bug,我特么直接一脱鞋扔过去。你家的Google Keep都有这个问题。
Snipaste_2021-03-02_00-04-43.png

不过你不想修就不想修吧,好在给出了解决方案,就是将android:fallbackLineSpacing属性设置为false。可以在代码中设置,也可以在XML中设置,都一样。
以下为自定义EditText部分的代码:

public class LinedEditText extends AppCompatEditText {
    private Paint paint = new Paint();
    // 文本行高
    private int lineHeight;

    private final float startX = 0.0f;

    public LinedEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.rgb(208, 208, 218));
        paint.setTextSize(getTextSize());

        lineHeight = getLineHeight();
        setGravity(Gravity.TOP); // 使文本框的显示方式为从上到下

        // 这是个巨坑: https://issuetracker.google.com/issues/131284662
        setFallbackLineSpacing(false);
    }

    @Override
    public void onDraw(Canvas canvas) {
        // 下划线绘制在文字底部,需要设置 lineSpacingExtra 的行间距,才能有空余区域显示出来。
        final float lineSpacingExtra = getLineSpacingExtra() / 2 + 1;
        final float stopX = getWidth();

        // 超过一屏能显示的文本内容没有有下划线
        int actualLineCount = getLineCount();
        int screenCount = (int) Math.ceil(getHeight() / lineHeight);
        int linesToDraw = Math.max(actualLineCount, screenCount) + 1;

        for (int i = 0; i < linesToDraw; i++) {
            float baseline = lineHeight * i - lineSpacingExtra;
            canvas.drawLine(startX, baseline, stopX, baseline, paint);
        }

        super.onDraw(canvas); // 画出光标才能编辑文本
    }
}

对应的XML为:

<com.racecoder.simplememo.view.LinedEditText
    android:id="@+id/add_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@+id/add_timebar"
    android:layout_marginLeft="20dp"
    android:layout_marginRight="20dp"
    android:background="@null"
    android:hint="@string/write_content_hint"
    android:textColorHint="@color/edit_hint_text"
    android:inputType="none|text|textMultiLine|textNoSuggestions"
    android:lineSpacingExtra="18dp"
    android:scrollbars="vertical"
    android:textColor="@color/edit_text"
    android:textSize="@dimen/Edit_Content_TextSize">

    <requestFocus />
</com.racecoder.simplememo.view.LinedEditText>

最终修复后效果:
fixed.gif

标签: none

添加新评论

ali-01.gifali-58.gifali-09.gifali-23.gifali-04.gifali-46.gifali-57.gifali-22.gifali-38.gifali-13.gifali-10.gifali-34.gifali-06.gifali-37.gifali-42.gifali-35.gifali-12.gifali-30.gifali-16.gifali-54.gifali-55.gifali-59.gif

加载中……