安卓API28以上自定义EditText的行间距不相等
由于之前用的一个便签应用在我换新手机后不兼容了,目前也没发现类似的便签应用,就花了半个月时间研究了下安卓程序开发,真实一把辛酸一把泪,坑的我这个javaer当场死亡。我特么绝壁再也不碰这辣鸡玩意了。
References:
- https://stackoverflow.com/questions/55845977/incorrect-edittext-line-spacing-behavior-in-target-api-28-when-dealing-with-non/56212644
- https://issuetracker.google.com/issues/131284662
- https://developer.android.com/reference/android/widget/TextView#attr_android:fallbackLineSpacing
给EditText添加下划线这个功能太常见了,基本上有多行文本编辑的地方都能看到,大多数实现方式就是自定义一个EditText重写onDraw方法自己画线,这里也不例外,然而在我给EditText加下划线的时候发生了这样的事:
换了多行之后不但线画的不准,偏移了,在一行内输入中英文时甚至会改变行高,我特么直接吐了,这让人还怎么划线。这里不管怎么计算ascent、decent、leading、fontMetrics这些乱七八糟的都没用。然后查了很久才找到问题所在,还得多亏了StackOverflow上的这位兄台,Google官方居然还大言不惭说这是Feature,不是Bug,我特么直接一脱鞋扔过去。你家的Google Keep都有这个问题。
不过你不想修就不想修吧,好在给出了解决方案,就是将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>最终修复后效果:
 这破站
                                        这破站                
仅有一条评论