(一)問題
怎樣實現帶有橫欄的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類]
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;
}
}
[布局文件]
<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>
[測試類]
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;
}
}