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新增至我們的Layout2.在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); }挪,結束了。