(一)自定義View類
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class CrossView extends View {
private float mRotation;
private Paint mPaint;
public CrossView( Context context, AttributeSet attrs ) {//AttributeSet對象在實例化時被系統傳給了視圖
super( context, attrs );
//start 創建paint對象
mPaint = new Paint();
mPaint.setAntiAlias( true );
mPaint.setColor( 0xFFFFFFFF );
//end 創建paint對象
//使用obtainStyledAttributes方法來創建一個TypedArray,這是訪問存儲於AttributeSet中的值的一個方便類,這類執行內部緩存,
//所以當你結束使用它之後隨時調用回收函數。注意:需同時使用<declare-styleable>名稱和<arr>名稱的訪問自定義屬性
TypedArray arr = getContext().obtainStyledAttributes( attrs,R.styleable.cross );
int color = arr.getColor( R.styleable.cross_android_color, Color.WHITE );
float rotation = arr.getFloat( R.styleable.cross_rotation, 0f );
//remember to call this when finished
arr.recycle();
setColor(color);
setRotation(rotation);
}
private void setRotation( float rotation ) {
// TODO Auto-generated method stub
mRotation = rotation;
}
private void setColor( int color ) {
// TODO Auto-generated method stub
mPaint.setColor( color );
}
//重寫onMeasure方法
@Override
protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec ) {
// TODO Auto-generated method stub
super.onMeasure( widthMeasureSpec, heightMeasureSpec );
//需要使用計算好的寬和高的值作為該方法的實參
setMeasuredDimension( calculateMeasure(widthMeasureSpec), calculateMeasure(heightMeasureSpec) );
}
float[] mPoints = {0.5f,0f,0.5f,1f,0f,0.5f,1f,0.5f};
@Override
protected void onDraw( Canvas canvas ) {
// TODO Auto-generated method stub
super.onDraw( canvas );
canvas.save();//所有的在畫布上繪圖的調用都應當受對應的sava()和restore()的約束
int scale = getWidth();
canvas.scale( scale, scale );
canvas.rotate( mRotation );
canvas.drawLines( mPoints, mPaint );//繪制十字的兩條線
canvas.restore();//所有的在畫布上繪圖的調用都應當受對應的sava()和restore()的約束
}
private static final int DEFAULT_SIZE = 100;//默認的試圖尺寸
//實現計算測量值的代碼
private int calculateMeasure(int measureSpec){
int result = ( int ) ( DEFAULT_SIZE*getResources().getDisplayMetrics().density );
int specMode = MeasureSpec.getMode( measureSpec );//在MeasureSpec中檢索模式
int specSize = MeasureSpec.getSize( measureSpec );//在MeasureSpec中檢索尺寸
//基於模式選擇尺寸
if(specMode == MeasureSpec.EXACTLY){
result = specSize;
}else if(specMode == MeasureSpec.AT_MOST){
result = Math.min( result, specSize );
}
return result;
}
}
(二)自定義屬性
<?xml version="1.0" encoding="utf-8"?>
<!-- 該文件被放置在res/values/目錄下 -->
<resources>
<!-- 聲明屬性 -->
<declare-styleable name="cross">
<attr name="android:color"/>
<attr name="rotation" format="string"/>
</declare-styleable>
<!--
<attr name="test" format="string"/>
<declare-styleable name="foo">
<attr name="test"/>
</declare-styleable>
<declare-styleable name="bar">
<attr name="test"/>
</declare-styleable> -->
</resources>
(三)在XML中使用自定義View
<?xml version="1.0" encoding="utf-8"?>
<!-- 要使用在XML中的自定義屬性,首先必須為視圖聲明命名空間 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:example="http://schemas.android.com/apk/res/com.example"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- 添加CrossView -->
<com.example.CrossView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<com.example.CrossView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
example.rotation="30"
android:color="#0000FF"/>
/>
<com.example.CrossView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
example.rotation="40"
android:color="#FFFF00"
/>
</LinearLayout>