在我們編寫android程序時一般是自定義以一個類繼承自Activity 並且重寫onCreate方法:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
setContentView()方法包含多個重載其中一個便是“setContentView(View view)”,也就是說可以直接通過一個View的實例來構建內容。我們嘗試放入一個TextView,上面的代碼變成了這樣:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
TextView sayHello = new TextView(this);
sayHello.setText("Hello world! I'm a TextView.");
setContentView(sayHello);
}
運行這段代碼,在模擬器上你應該可以看到以下結果:
如此簡單不是嗎?好吧讓我們再讓它豐富點:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
// TextView sayHello = new TextView(this);
// sayHello.setText("Hello world! I'm a TextView.");
setContentView(new SayHello(this));
}
class SayHello extends View{
public SayHello(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint mPaint=new Paint() ;
mPaint.setTextSize(22f);
mPaint.setColor(Color.RED);
canvas.drawText("Hello world! I'm a TextView.", 0, 100, mPaint);
}
}
這次我們自定義了一個局部類SayHello 繼承自View並且重寫了 onDraw 方法(需要注意的是由於View沒有無參構造函數所以我們爲其指定實現哪一個構造函數)。在onDraw 方法中我們定義了一個Paint,現在你只需要理解它有繪畫的功能即可,那麼它要在哪裏繪畫呢?答案就是在Canvas上,可以把Canvas理解成畫布。
現在我們設置mPaint的字體大小爲22F 顏色爲紅色,然後在畫布上寫出“Hello world。。。”這幾個紅色的字,並且把onCreate裏的setContentView 爲setContentView(new SayHello(this));
最後在模擬器上你應該看到的是:
so cool! 不是嗎?
不!不對,我們在Android的開發View不是這樣的,它應該是通過 Xml.......@##¥%
好吧 讓我們再把例子修改一下。
首先我們將SayHello 類提取出來,並且將它放入一個單獨的類文件中,接下來就是重點:我們需要添加另外的一些構造函數以便給View傳遞參數,最好你看到的SayHello 類應該是這樣的:
public class SayHello extends View {
public SayHello(Context context)
{
super(context);
}
public SayHello(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public SayHello(Context context, AttributeSet attrs,int defStyle)
{
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint mPaint=new Paint() ;
mPaint.setTextSize(22f);
mPaint.setColor(Color.RED);
canvas.drawText("Hello world! I'm a TextView.", 0, 100, mPaint);
}
}
這裏簡單講解一下新增的構造函數的作用,在新的構造函數中爲View的構造函數傳遞了AttributeSet attrs,int defStyle兩個參數,這代表着該View可以通過XML 來創建並且接受Style來設定樣式。等到相關博文時會再具體講解。
接下來,我們恢復Activity類裏的onCreate方法讓它看起來像這個樣子:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
和一開始沒啥兩樣對吧。
最後我們需要去修改佈局文件main 在文件里加入以下 xml標籤:
<com.××××.customview.SayHello
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</com.××××.customview.SayHello>
(注意××××,代表SayHello類所在的包,這裏需要的是全名)。
然後再次運行程序,你應該看到以下結果:
是不是和我們平常定義View時很像了?
你感覺得還不夠,還缺乏些什麼?
好吧,你很聰明,我們的Text應該是在XML上通過某個屬性配置而成的,而不是寫在代碼裏!
爲了將SayHello的屬性暴露到XMl上首先我們需要在res/value 文件夾下新建一個XMl文件,命名爲:atts。
在裏面添加如下代碼:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SayHello">
<attr name="content" format="string"></attr>
<attr name="text_color" format="color"></attr>
</declare-styleable>
</resources>
需要注意的是這裏是沒有智能提示的
然後我們需要修改SayHello類,還記得那個AttributeSet嗎?我們將通過它來獲取XML配置上的屬性值。修改後的SayHello類代碼是這樣的:
private int mColor;
private String mContent;
public SayHello(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray typeArray = context.obtainStyledAttributes(attrs,
R.styleable.SayHello);
mColor=typeArray.getColor(R.styleable.SayHello_text_color, 0XFF00FF00);
mContent=typeArray.getString(R.styleable.SayHello_content);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint mPaint = new Paint();
mPaint.setTextSize(22f);
mPaint.setColor(mColor);
canvas.drawText(mContent, 0, 100, mPaint);
}
現在可以去XML上爲哥哥屬性添加值了,不過先彆着急我們的得將命名空間告訴它。
在佈局文件的根源是上(通常是Layout)添加: xmlns:SayHello="http://schemas.android.com/apk/res/com.XXXX.customview"
SayHello 可以爲您任意想要定義的名字,它將作爲屬性的前綴使用就像android:Layout 一樣而我們的爲:SayHello:content,後半段http://schemas.android.com/apk/res/ 爲固定值,緊接着的是你整個APP的包命名,你不知道自己包名稱?趕去去 AndroidManifest.xml文件中看看吧(注意該包名需要保持和manifest中的 package 保持一致,否則會提示無法找到XML屬性)。
最後我們終於可以在XML上定義自己想要的字體顏色的內容了:
<com.XXXX.customview.SayHello
android:layout_width="fill_parent"
android:layout_height="wrap_content"
SayHello:text_color="#1212f0"
SayHello:content="this is a xml attr view">
</com.XXXX.customview.SayHello>
運行程序您應該會看到以下結果:
這就是我們View 一般的定義方式和過程。