android - 在使用自定义字体或字样的 EditText 中绘制背景线

标签 android fonts android-edittext typeface

我正在尝试对 EditText 进行子类化,以创建一个带有水平线的新文本框(如横格纸上所示)。这是我的基本代码:

public class LinedEditText extends EditText {

    // the paint we will use to draw the lines
    private Paint dashedLinePaint;

    // a reusable rect object
    private Rect reuseableRect;

    public LinedEditText(Context context) {
        super(context);
        init();
    }

    public LinedEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public LinedEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    /**
     * Initialize the paint object.
     */
    private void init() {

        // instantiate the rect
        reuseableRect = new Rect();

        // instantiate the paint
        dashedLinePaint = new Paint();
        dashedLinePaint.setARGB(200, 0, 0, 0);
        dashedLinePaint.setStyle(Style.STROKE);
        dashedLinePaint.setPathEffect(new DashPathEffect(new float[]{4, 6}, 0));
    }

    @Override
    protected void onDraw(Canvas canvas) {

        Log.e("LINE_HEIGHT", "Line height for typeface is " + getLineHeight());

        // get the height of the view
        int height = getHeight();

        // get the height of each line
        int lineHeight = getLineHeight();

        // the number of lines equals the height divided by the line height
        int numberOfLines = height / lineHeight;

        // if there are more lines than what appear on screen
        if (getLineCount() > numberOfLines) {

            // set the number of lines to the line count
            numberOfLines = getLineCount();
        }

        // get the rectangle instance
        Rect r = reuseableRect;

        // get the baseline for the first line
        int baseline = getLineBounds(0, r);

        // for each line
        for (int i = 0; i < numberOfLines; i++) {

            // draw the line
            canvas.drawLine(
                    r.left,                 // left
                    baseline,               // top
                    r.right,                // right
                    baseline,               // bottom
                    dashedLinePaint);       // paint instance

            // get the baseline for the next line
            baseline += getLineHeight();
        }

        super.onDraw(canvas);
    }
}

...当我使用默认系统字体时,效果非常好:

01-20 15:31:08.172 3966-3966/com... E/LINE_HEIGHT: Line height for typeface is 63

with system font

但是当我调用 linedEditTextBox.setTypeface(typeface) 时,它就会这样绘制:

01-20 15:33:58.938 4064-4064/com... E/LINE_HEIGHT: Line height for typeface is 83

with custom font

有谁知道这里发生了什么吗?我是否应该在子类中重写 setTypeface,并进行某种类型的计算来确定新的行高?我很困惑,任何意见都会受到赞赏。

以下是我看过的其他一些似乎相关的 StackOverflow 问题: EditText draw lines wrong Drawing multiple lines in edittext e.g. notepad

最佳答案

想通了。由于某种原因,我必须从 getLineHeight() 返回的行高中减去一,不知道为什么。现在它可以工作了,这里是该类的完整代码:

public class LinedEditText extends EditText {

    // the vertical offset scaling factor (10% of the height of the text)
    private static final float VERTICAL_OFFSET_SCALING_FACTOR = 0.1f;

    // the dashed line scale factors
    private static final float DASHED_LINE_ON_SCALE_FACTOR = 0.008f;
    private static final float DASHED_LINE_OFF_SCALE_FACTOR = 0.0125f;

    // the paint we will use to draw the lines
    private Paint dashedLinePaint;

    // a reusable rect object
    private Rect reuseableRect;

    public LinedEditText(Context context) {
        super(context);
        init();
    }

    public LinedEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public LinedEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {

        // instantiate the rect
        reuseableRect = new Rect();

        // instantiate the paint
        dashedLinePaint = new Paint();
        dashedLinePaint.setARGB(200, 0, 0, 0);
        dashedLinePaint.setStyle(Style.STROKE);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        // set the path effect based on the view width
        dashedLinePaint.setPathEffect(
                new DashPathEffect(
                        new float[]{
                                getWidth() * DASHED_LINE_ON_SCALE_FACTOR,
                                getWidth() * DASHED_LINE_OFF_SCALE_FACTOR},
                        0));

        // get the height of the view
        int height = getHeight();

        // get the height of each line (not subtracting one from the line height makes lines uneven)
        int lineHeight = getLineHeight() - 1;

        // set the vertical offset basef off of the view width
        int verticalOffset = (int) (lineHeight * VERTICAL_OFFSET_SCALING_FACTOR);

        // the number of lines equals the height divided by the line height
        int numberOfLines = height / lineHeight;

        // if there are more lines than what appear on screen
        if (getLineCount() > numberOfLines) {

            // set the number of lines to the line count
            numberOfLines = getLineCount();
        }

        // get the baseline for the first line
        int baseline = getLineBounds(0, reuseableRect);

        // for each line
        for (int i = 0; i < numberOfLines; i++) {

            // draw the line
            canvas.drawLine(
                    reuseableRect.left,             // left
                    baseline + verticalOffset,      // top
                    reuseableRect.right,            // right
                    baseline + verticalOffset,      // bottom
                    dashedLinePaint);               // paint instance

            // get the baseline for the next line
            baseline += lineHeight;
        }

        super.onDraw(canvas);
    }
}

现在看起来正确:

correct with new font

关于android - 在使用自定义字体或字样的 EditText 中绘制背景线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21243969/

相关文章:

css - 如何设置全局字体 - CSS

android - 如果我应用背景,如何在 EditText 上返回默认样式?

Android Word-Wrap EditText 文本

css - SVG 元素的字体可以在 CSS 文件中声明吗?

android - 下载图像文件并替换现有图像文件

android: 我可以为 viewflipper 的不同 child 使用不同的类吗

Android在动态加载图像时显示进度条

java - Swing 缩放组件的文本字体

android - setCompoundDrawablesWithIntrinsicBounds(int,int,int,int)不起作用

android - 将总是可见的聊天头的 LayoutParams 更改为不总是可见