1.SDK需使用含Google APIs [Android x.x]的,而非單純的 [Android x.x]
因為我們使用Google API s[Android 2.2] (而非只是[Android 2.2]) ,maps.jar會直接被匯入到APIs裡,而不用自己另外匯入maps.jar
2.
這行要宣告在AndroidManifest.xml的
這行要宣告在AndroidManifest.xml的
TextView text = new TextView(this);
text.setText("test");
我們的Layout.addView(text); //將TextView新增至我們的Layout
2.在xml裡宣告<TextView
android:layout_width="fill_parent"
android:layout_height="warp_content"
android:text="test"/>
於是,我們可以很順利的得到這個畫面<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.test.testcustomize"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<com.test.testcustomize.LabelView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:text="Reddd" />
</LinearLayout>
有注意到嗎?多了xmlns:app="http://schemas.android.com/apk/res/com.test.testcustomize" app:text="Reddd"這時候你會問︰
app:text="Reddd"這個標籤怎麼來的?
app:text="Reddd"卻呈現了藍色、而且更大的字體。
package com.test.testcustomize;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class LabelView extends View {
private Paint mTextPaint;
private String mText;
private int mAscent;
public LabelView(Context context) {
super(context);
initLabelView();
}
public LabelView(Context context, AttributeSet attrs) {
super(context, attrs);
initLabelView();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequence s = a.getString(R.styleable.LabelView_text);
if(s!=null){
setText(s.toString());
}
setTextColor(a.getColor(R.styleable.LabelView_textColor, 0xFF0000FF));
int textSize = a.getDimensionPixelOffset(R.styleable.LabelView_textSize, 0);
if (textSize > 0) {
setTextSize(textSize);
}
a.recycle();
}
private void initLabelView(){
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(24);
mTextPaint.setColor(0xFF000000);
setPadding(3,3,3,3);
}
private void setText(String str){
mText = str;
requestLayout();
invalidate(); //每呼叫一次就會重新繪圖onDraw()
}
/**
* Sets the text size for this label
* @param size Font size
*/
public void setTextSize(int size) {
mTextPaint.setTextSize(size);
requestLayout();
invalidate(); //每呼叫一次就會重新繪圖onDraw()
}
/**
* Sets the text color for this label.
* @param color ARGB value for the text
*/
public void setTextColor(int color) {
mTextPaint.setColor(color);
invalidate(); //每呼叫一次就會重新繪圖onDraw()
}
/**
* @see android.view.View#measure(int, int)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}
/**
* Determines the width of this view
* @param measureSpec A measureSpec packed into an int
* @return The width of the view, honoring constraints from measureSpec
*/
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = (int) mTextPaint.measureText(mText) + getPaddingLeft()
+ getPaddingRight();
if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}
/**
* Determines the height of this view
* @param measureSpec A measureSpec packed into an int
* @return The height of the view, honoring constraints from measureSpec
*/
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
mAscent = (int) mTextPaint.ascent();
Log.i("tag", "Height Ascent: "+mAscent);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = (int) (-mAscent + mTextPaint.descent()) + getPaddingTop()
+ getPaddingBottom();
Log.i("tag", "Height mTextPaint.descent(): "+mTextPaint.descent());
if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent, mTextPaint);
}
}
Code很長,請聽我一一道來。//建構式1
public LabelView(Context context) {
super(context);
initLabelView(); //設定文字的最初樣式
}
//建構式2
public LabelView(Context context, AttributeSet attrs) {
super(context, attrs);
initLabelView(); //設定文字的最初樣式
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequence s = a.getString(R.styleable.LabelView_text);
if(s!=null){
setText(s.toString());
}
setTextColor(a.getColor(R.styleable.LabelView_textColor, 0xFF0000FF));
int textSize = a.getDimensionPixelOffset(R.styleable.LabelView_textSize, 0);
if (textSize > 0) {
setTextSize(textSize);
}
a.recycle();
}
技術文件裡提到,initLabelView();該函式的內容如下︰
private void initLabelView(){
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true); //設定反鉅齒
mTextPaint.setTextSize(24); //設定預設大小為24
mTextPaint.setColor(0xFF000000); //設定預設的顏色為黑字體
setPadding(3,3,3,3); //設定在版面上下左右各距離3
}
我們在輸入文字的一開始,//建構式2
public LabelView(Context context, AttributeSet attrs) {
super(context, attrs);
initLabelView();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequence s = a.getString(R.styleable.LabelView_text);
if(s!=null){
setText(s.toString());
}
setTextColor(a.getColor(R.styleable.LabelView_textColor, 0xFF0000FF));
int textSize = a.getDimensionPixelOffset(R.styleable.LabelView_textSize, 0);
if (textSize > 0) {
setTextSize(textSize);
}
a.recycle();
}
第6行︰將我們自己做的attrs.xml呼叫進來/**
* @see android.view.View#measure(int, int)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}
2.最後呼叫onDraw()繪圖/**
* 量測這個View的寬
* @param measureSpec A measureSpec packed into an int
* @return The width of the view, honoring constraints from measureSpec
*/
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = (int) mTextPaint.measureText(mText) + getPaddingLeft()
+ getPaddingRight();
if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}
/**
* 量測這個View的高
* @param measureSpec A measureSpec packed into an int
* @return The height of the view, honoring constraints from measureSpec
*/
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
mAscent = (int) mTextPaint.ascent();
Log.i("tag", "Height Ascent: "+mAscent);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = (int) (-mAscent + mTextPaint.descent()) + getPaddingTop()
+ getPaddingBottom();
Log.i("tag", "Height mTextPaint.descent(): "+mTextPaint.descent());
if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}
第6行︰一開始系統傳進來的引數measureSpec是從main.xml裡抓過來的
AT_MOST
| |||
EXACTLY
| |||
UNSPECIFIED
|
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent, mTextPaint);
}
挪,結束了。