이전에 EditText에 밑줄을 표시하는 예제를 작성했으나 여전히 몇 가지 문제가 발견되어 이를 계속해서 탐구해 봅니다. 원문 링크: http://www.cnblogs.com/ayqy/p/3599414.html
0. 또 다른 버그
만약 선이 그려지지 않는다면, canvas.drawLine 메서드의 마지막 매개변수인 paint의 선 두께(lineWidth) 문제일 수 있습니다. Android 2.3.5에서는 선 두께 0.5로 정상적으로 선이 그려지지만, Android 4.2.2에서는 선 두께 0.5로 선이 그려지지 않습니다. 구체적인 내용은 다음과 같습니다:
// 선 두께에 주의하세요. Android 2.3.5에서는 0.5로 정상적으로 그려지지만, Android 4.2.2에서는 0.5로 그려지지 않습니다. lineWidth = 1.0f;// 기본 두께는 1.0으로 설정
그래도 선이 그려지지 않는다면 시작점 좌표를 확인하세요. 선 그리기 시 시작점이 가시 범위 내에 없으면 선 전체가 보이지 않습니다. TextView의 가시 영역은 컨트롤이 차지하는 직사각형 영역입니다. 구체적인 내용은 다음과 같습니다:
// 선 그리기 시 시작점이 가시 범위 내에 없으면 선 전체가 보이지 않습니다. TextView의 가시 영역은 컨트롤이 차지하는 직사각형 영역입니다. canvas.drawLine(padL//startX , baseTop + gap * i//startY , this.getWidth() - padR//endX , baseTop + gap * i//endY , mPaint);
1. 문제
이전의 커스텀 EditText는 텍스트 내용의 높이가 화면 높이를 넘지 않을 때만 정상적으로 표시되었습니다. 내용이 화면을 넘어가면 다음과 같은 문제가 발생했습니다:
2. 원인 분석
하단부(화면 높이를 초과하는 부분)에 선이 더 이상 그려지지 않았습니다. 즉, 가로선이 충분히 그려지지 않은 것이며, 이는 반복문 제어 부분에 문제가 있다는 것을 의미합니다.
3. 해결 방법
1. 어떻게 해야 모든 텍스트 줄 아래에 선을 그릴 수 있을까요?
먼저 EditText.getLineCount()를 사용하여 텍스트의 총 줄 수를 가져온 다음, 줄 수만큼 선을 그리면 됩니다.
2. 가로선의 위치는 어떻게 결정할까요?
Y = EditText.getPaddingTop() + EditText.getLineHeight() * index;// Y 좌표 = 텍스트 상자 상단 여백 + 줄 높이 * 줄 인덱스(몇 번째 줄인지)
위의 방법은 위에서 아래로 선을 그리는 방식입니다. 물론 아래에서 위로 선을 그릴 수도 있지만, 여기서는 다루지 않겠습니다.
4. 코딩
package com.ayqy.app_test;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.widget.EditText;
public class myEditText extends EditText{
private int lineColor;// 가로선 색상
private float lineWidth;// 가로선 두께
public myEditText(Context context) {
super(context);
// 기본 색상 및 가로선 두께 설정
lineColor = Color.BLUE;// 기본 파란색 선
lineWidth = 0.5f;// 기본 두께 0.5
}
public myEditText(Context context,int color,float width) {
super(context);
// 색상 및 가로선 두께 설정
this.lineColor = color;
this.lineWidth = width;
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
// Paint 객체 생성
Paint mPaint = new Paint();
mPaint.setStrokeWidth(lineWidth);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(lineColor);
// 파라미터 가져오기
int padL = this.getPaddingLeft();// 왼쪽 여백 가져오기
int padR = this.getPaddingRight();// 오른쪽 여백 가져오기
int padT = this.getPaddingTop();// 상단 여백 가져오기
int lines = this.getLineCount();// 총 줄 수 가져오기
float size = this.getTextSize();// 글꼴 크기 가져오기
float baseTop = padT + size / 6;// 위에서 첫 번째 선의 위치
/* 여기서 설명이 필요한 부분은 size / 6 이라는 값입니다. 이는 테스트를 통해 우연히 얻은 값으로, 줄 간격의 절반에 가깝습니다.
* 왜 EditText.getLineSpacingExtra()를 사용하여 줄 간격을 가져오지 않았을까요?
* 테스트 결과 EditText의 getLineSpacingExtra 메서드를 호출하면 NoSuchMethod 오류가 발생했기 때문입니다. 정확한 원인은 알 수 없습니다.
* 테스트를 통해 줄 간격 값이 TextSize의 1/3에 가깝다는 것을 알았으며, 줄 간격이 필요할 때 getLineSpacingExtra 메서드 대신 이 값을 사용할 수 있습니다.
* */
float gap = this.getLineHeight();// 줄 높이 가져오기
// 위에서 아래로 선 그리기
for(int i = 1;i <= lines;i++)
{
canvas.drawLine(padL//startX
, baseTop + gap * i//startY
, this.getWidth() - padR//endX
, baseTop + gap * i//endY
, mPaint);
}
}
public int getLineColor() {
return lineColor;
}
public void setLineColor(int color) {
this.lineColor = color;
}
public float getLineWidth() {
return lineWidth;
}
public void setLineWidth(float width) {
this.lineWidth = width;
}
}
P.S. 위의 코드 주석에서 "테스트 결과 EditText의 getLineSpacingExtra 메서드를 호출하면 NoSuchMethod 오류가 발생한다"고 언급했는데, Google에 검색해 봐도 이 문제를 겪은 사람이 없는 것 같습니다. 혹시 답을 아시는 분은 아래에 댓글 남겨주시면 감사하겠습니다.
5. 결과 화면
수정된 코드는 "문자가 선에 겹치는 문제"와 "커서가 선에 겹치는 문제"를 완벽하게 해결했습니다. 핵심은 줄 간격 = TextSize / 3 이라는 점이며, 줄 간격의 존재가 뷰 표시에 영향을 주므로 반 줄 간격을 더해주면 됩니다.
6. 마무리
버그를 발견하고 즉시 수정하는 것, 이것이 바로 프로그래밍의 즐거움입니다.
아직 댓글이 없습니다