Android實現自帶橫線的EditText


(一)問題

怎樣實現帶有橫欄的EditText(像記事本的編輯界面那樣)?

(二)初步思路

1.通過修改EditText背景來實現(系統背景是一個框形圖片,內部透明,替換為一個帶有橫欄的圖片即可)

2.通過重繪EditText來實現(自定義組件,自己畫線)

3.用ListView實現(ListView本身就會顯示橫線)

(三)深入分析

1.EditText顯示多行文本時會自動拉伸背景,若要保證邊框不會失真,需要用9patch圖片來做背景,或許能夠實現

2.毫無疑問,自定義EditText一定可以實現橫線的顯示(沒有槍炮就自己造...),但是自定義組件比較麻煩(需要重寫很多東西),能用其他方法解決當然更好

3.ListView用來顯示多行文本可能比較好(將Text分割為等長String存入Array,作為ListView的Adapter),但是若要編輯文本則明顯不合適

(四)初步實踐

1.通過多次測試發現改變EditText的背景圖能夠顯示橫欄,但僅限於SingLine的文本,因為輸入多行文本時背景圖會向下拉伸(橫線沒了...)。所以測試結果是:用自定義背景圖只能顯示帶下划線的單行文本,方案一失敗!但是在此過程中學到了9patch圖片的用處,算是一點小收獲。

2.通過重寫EditText的onDraw方法來繪制需要的橫線,如何確定橫線的位置成為核心問題(本質是獲取一組起點坐標和一組對應的終點坐標),此方法在下面展開詳述

3.ListView的缺點在上面已經說過了,但是經過對方案一的嘗試,我們很容易發現方案一和方案三恰好互補(把方案一得到的EditText作為ListView的Item),此時應該為EditText自定義selector,設置focus時不發光即可。測試結果是:單行EditText負責按行顯示文本,ListView負責畫線,方案一組合方案三可行。

(五)自定義EditText實現橫欄的顯示

[自定義myEditText類]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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 = 2f; //寬度為2
     }
     
     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 mPaint =  new  Paint();
         mPaint.setStrokeWidth(lineWidth);
         mPaint.setStyle(Paint.Style.FILL);
         mPaint.setColor(lineColor);
         
         //獲取參數
         int  w =  this .getWidth(); //獲取控件寬度
         int  h =  this .getHeight(); //獲取控件高度
         int  padB =  this .getPaddingBottom(); //獲取底部留白
         int  padL =  this .getPaddingLeft(); //獲取左邊留白
         int  padR =  this .getPaddingRight(); //獲取右邊留白
         float  size =  this .getTextSize() *  7  6 ; //獲取橫欄間距(TextSize的默認值為18)
         /*設置size的值是一個核心問題,size的值要適應不同的字體大小(不同大小字體的行距也不同)
          *經過多次嘗試發現以字體大小的7/6倍作為橫欄間距最合適
          * */
         int  lines = ( int )(h / size); //獲取行數
         
         //從下向上畫線
         for ( int  i =  0 ;i < lines;i++)
             canvas.drawLine(padL //startX
                     this .getHeight() - padB - size * i //startY
                     this .getWidth() - padR //endX
                     this .getHeight() - padB - size * 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;
     }
 
}

[布局文件]

[測試類]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package  com.ayqy.app_test;
 
import  android.app.Activity;
import  android.os.Bundle;
import  android.view.Menu;
import  android.widget.LinearLayout;
 
public  class  MainActivity  extends  Activity {
     
     LinearLayout root; //聲明根布局
 
     @Override
     protected  void  onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         
         root = (LinearLayout) findViewById(R.id.root); //獲取根布局
         //創建自定義EditText控件對象
         myEditText txt =  new  myEditText( this );
         //設置多行文本
         txt.setText( "這是一個很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長的測試內容" );
         //用來測試是否能夠適應不同大小的字體
         //txt.setTextSize(48);
         //txt.setTextSize(24);
         root.addView(txt); //添加控件
     }
 
     @Override
     public  boolean  onCreateOptionsMenu(Menu menu) {
         // Inflate the menu; this adds items to the action bar if it is present.
         getMenuInflater().inflate(R.menu.main, menu);
         return  true ;
     }
 
}

[P.S.以上源碼本機測試無誤,若在測試中發現任何問題請在下方留言]

(六)測試結果圖片

(七)總結

嘗試是解決問題的最好方法,即便最終問題得不到解決,其間的思考也是一種鍛煉

(八)BUG修正

此版本存在BUG,詳情及修正方法見 http://www.cnblogs.com/ayqy/p/3600289.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM