From the tutorial I have created the layout:
public static class LinedEditText extends EditText {
private Rect mRect;
private Paint mPaint;
// we need this constructor for LayoutInflater
public LinedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mRect = new Rect();
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(0x80000000);
}
@Override
protected void onDraw(Canvas canvas) {
int count = getLineCount();
Rect r = mRect;
Paint paint = mPaint;
for (int i = 0; i < count; i++) {
int baseline = getLineBounds(i, r);
canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
}
super.onDraw(canvas);
}
}
<view xmlns:android="http://schemas.android.com/apk/res/android"
class="com.bbbfr.mynotepad.NotepadText$LinedEditText"
android:id="@+id/note"
android:background="#ffd6e5"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp"
android:scrollbars="vertical"
android:fadingEdge="vertical"
android:gravity="top"
android:textSize="22sp"
android:textColor="#000000"
android:inputType="textMultiLine"
android:capitalize="sentences"
/>
This makes only the first line underlined. Is it possible to make all the lines underlined, even if there is only one line in the edtittext?
I tried changing the loop e.g. for (int i = 0; i < 5; i++)
but then I receive this error:
04-28 08:29:05.093: E/AndroidRuntime(14398):
java.lang.IndexOutOfBoundsException: 2, 1 04-28 08:29:05.093:
E/AndroidRuntime(14398): at
android.text.PackedIntVector.getValue(PackedIntVector.java:70) 04-28
08:29:05.093: E/AndroidRuntime(14398): at
android.text.DynamicLayout.getLineTop(DynamicLayout.java:367) 04-28
08:29:05.093: E/AndroidRuntime(14398): at
android.text.Layout.getLineBottom(Layout.java:831) 04-28 08:29:05.093:
E/AndroidRuntime(14398): at
android.text.Layout.getLineBounds(Layout.java:437) 04-28 08:29:05.093:
E/AndroidRuntime(14398): at
android.widget.TextView.getLineBounds(TextView.java:4122) 04-28
08:29:05.093: E/AndroidRuntime(14398): at
com.bbbfr.mynotepad.NotepadText$LinedEditText.onDraw(NotepadText.java:56)
to this line: int baseline = getLineBounds(i, r);
I have also set android:lines="5"
in the view.
If you don't mind the underline having the same colour as the text in the EditText
, you should really just use the built-in UnderlineSpan
, either by creating it yourself or indirectly through Html.fromHtml(...)
.
private void createUnderlinedText() {
String text = "I am underlined text\nLine #2\nLine #3\nLine #4\nLine #5";
EditText underlineSpanEditText = (EditText) findViewById(R.id.underlinespan_edittext);
SpannableStringBuilder sb = new SpannableStringBuilder(text);
sb.setSpan(new UnderlineSpan(), 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
underlineSpanEditText.setText(sb);
EditText htmlUnderlineEditText = (EditText) findViewById(R.id.html_underline_edittext);
String html = "<u>I am underlined text</br>Line #2</br>Line #3</br>Line #4</br>Line #5</u>";
htmlUnderlineEditText.setText(Html.fromHtml(html));
}
The main difference with your current approach is that this will only underline the actual text, and not the whole text line. For example, if you run my code snippet, you will find that the underline does not extend to the end of the line when it's broken off by the \n
or <br/>
. However, depending on the behaviour your after, this may not be what you're looking for.
Edit: So if I understand you correctly, you basically want to keep drawing horizontal lines in your EditText
, no matter wether there is text or not? The 'underline' part in your question was kind of misleading, since, as it turns out, that has little to do with it (in the traditional meaning of the word :)).
Anyways, you can't use getLineCount()
since that will always return the number of lines that contain actual text. That would mean you would have to 'fill' any remaing space with new line characters to get the desired effect, which sounds kind of yucky... A better alternative is probably to base the drawing of horizontal lines on the total height of the EditText
. A quick example, which you can obviously tweak to your own liking:
public class LinedEditText extends EditText {
private Paint mPaint = new Paint();
public LinedEditText(Context context) {
super(context);
initPaint();
}
public LinedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
}
public LinedEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initPaint();
}
private void initPaint() {
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(0x80000000);
}
@Override protected void onDraw(Canvas canvas) {
int left = getLeft();
int right = getRight();
int paddingTop = getPaddingTop();
int paddingBottom = getPaddingBottom();
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
int height = getHeight();
int lineHeight = getLineHeight();
int count = (height-paddingTop-paddingBottom) / lineHeight;
for (int i = 0; i < count; i++) {
int baseline = lineHeight * (i+1) + paddingTop;
canvas.drawLine(left+paddingLeft, baseline, right-paddingRight, baseline, mPaint);
}
super.onDraw(canvas);
}
}
The result looks like this:
As it is visible from your code, you are drawing underline
for the edit text
for lines from 0 to count
in your for loop and count
is set to int count = getLineCount();
. So only the existing number of lines in the EditText will be incremented! By changing the number of count you can draw as many underlines as you want!
The simplest workaround is that you can invoke setText with only line seperators in the constructor, e.g. "\n\n\n" (You can dynamic build it based on how many lines you need), then your current LinedEditText will have the underlines as you want.