我正在尝试对 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
但是当我调用 linedEditTextBox.setTypeface(typeface) 时,它就会这样绘制:
01-20 15:33:58.938 4064-4064/com... E/LINE_HEIGHT: Line height for typeface is 83
有谁知道这里发生了什么吗?我是否应该在子类中重写 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);
}
}
现在看起来正确:
关于android - 在使用自定义字体或字样的 EditText 中绘制背景线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21243969/