Android - 如何使edittext中的所有行加下划线?

问题描述:

从我所创建的布局教程:Android - 如何使edittext中的所有行加下划线?

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" 
/> 

这使得只有第一线下划线。即使在edtittext中只有一行,是否可以将所有行加下划线?

我试着改变环,例如for (int i = 0; i < 5; i++)但后来我收到此错误:

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)

这一行:int baseline = getLineBounds(i, r);

我也曾在视图设置android:lines="5"

如果你不介意在 EditText的颜色与文本相同的下划线,你真的应该只使用内置 UnderlineSpan,方法是通过 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)); 
} 

与您目前的方法的主要区别是,这只会强调实际文本,而不是整个文本行。例如,如果您运行我的代码片段,则会发现下划线不会在 \n<br/>中断时延伸到行尾。但是,根据你以后的行为,这可能不是你想要的。


编辑:所以,如果我理解正确的话,你基本上要不断吸引水平线在你的EditText,不管羯羊有文字或没有?你的问题中的'下划线'部分是有误导性的,因为事实证明,这与它无关(在这个词的传统意义上:))。

无论如何,你不能使用getLineCount(),因为它总是会返回包含实际文本的行数。这意味着你将不得不使用新的线条字符填充任何剩余空间以获得所需的效果,这听起来有点不可取...更好的替代方案可能是将水平线的绘制基于EditText的总高度。一个简单的例子,你可以明显地调整你自己的喜好:

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); 
    } 
} 

结果看起来是这样的:

LinedEditText

+0

@ erdomester:对不起,我在你的问题中的'下划线'部分犯了一个错误的脚。请看看我的答案中的编辑内容,希望能够解决更多与您对抗的问题。 – 2012-04-28 11:33:14

+0

这是一个伟大的方法!类定义必须是静态的,否则我会在setContentView(R.layout.notepadtext)中出错。 line.T非常感谢你! – erdomester 2012-04-28 12:37:11

+0

甜如。 :)你必须声明这个类是静态的,因为你可能将它实现为一个嵌套类,看到给出的XML:'com.bbbfr.mynotepad.NotepadText $ LinedEditText'。如果你想将它重构为一个单独的文件,你可以删除'static'并直接引用它 - 虽然没有任何区别。 – 2012-04-28 22:24:56

因为它是从你的代码可见,你在你的for循环和count绘制underlineedit text0 to count线被设置为int count = getLineCount();。所以只有EditText中现有的行数会增加!通过改变计数的数量,您可以根据需要绘制尽可能多的下划线!

+0

我也想过这个!但是当我将它改为例如5我收到一个错误,请参阅更新后的文章 – erdomester 2012-04-28 08:29:26

+0

,这是因为您的文本可能没有5行。你需要设置android:lines =“5”,在你的edittext中有5行,你可以在上面画下划线。 – 2012-04-28 08:31:23

+0

我做到了。我确信我有线=“5”,也有5个循环。 – erdomester 2012-04-28 08:33:20

最简单的解决方法是,你可以调用的setText与仅行分隔符构造函数,例如“\ n \ n \ n”(你可以根据你需要的行数来动态构建它),那么你当前的LinedEditText将会有你想要的下划线。