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
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
     xmlns:tools= "http://schemas.android.com/tools"
     android:id= "@+id/root"
     android:layout_width= "match_parent"
     android:layout_height= "match_parent"
     android:orientation= "vertical"
     tools:context= ".MainActivity"  >
 
</LinearLayout>

[测试类]

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值