package xena.view;
import xena.act.R;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class MyView extends View {
private Context context;
private int r = 10;
private String str = "小";
private final String NS = "http://www.hqyj.com";// 名稱空間
private boolean flag;
public float getR() {
return r;
}
public void setR(int r) {
this.r = r;
this.invalidate();//觸發onDraw方法的執行
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
this.invalidate();//觸發onDraw方法的執行
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
this.invalidate();//觸發onDraw方法的執行
}
// 用於自定義View當作標籤時用的
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
// 參數1:名稱空間, 參數2:自定義屬性名, 取失敗時當作默認值返回
this.r = attrs.getAttributeIntValue(NS, "r", 20);
// this.flag = attrs.getAttributeBooleanValue(NS, "flag", false);
// 參數1:我稱空間, 參數2: 自定義屬性名
// this.str = attrs.getAttributeValue(NS, "text");
// 如果屬性值是資源文件id
// int getAttributeResourceValue(String namespace, String attributeName,
// int defaultValue);
int id = attrs.getAttributeResourceValue(NS, "text", -1);
if (id != -1) {
// int id = R.string.hello_world;
Resources resources = this.context.getResources();
this.str = resources.getString(id);
}else {
this.str = attrs.getAttributeValue(NS, "text");
}
}
// 用於new MyView(...)用的
public MyView(Context context) {
super(context);
}
private int getwidth(int widthMeasureSpec) {
int width = 10;
int width_mode = MeasureSpec.getMode(widthMeasureSpec);
if(width_mode==MeasureSpec.EXACTLY) {
width = MeasureSpec.getSize(widthMeasureSpec);
}else if(width_mode==MeasureSpec.AT_MOST) {
width = (int) (2*r);
}else if(width_mode==MeasureSpec.UNSPECIFIED) {
width = 100;
}
return width;
}
// 00 11 10 11
private int getheight(int heightMeasureSpec) {
int hight = 10;
int hight_mode = MeasureSpec.getMode(heightMeasureSpec);
if(hight_mode==MeasureSpec.EXACTLY) {
hight = MeasureSpec.getSize(heightMeasureSpec);
}else if(hight_mode==MeasureSpec.AT_MOST) {
hight= (int) (2*r);
}else if(hight_mode==MeasureSpec.UNSPECIFIED) {
hight = 100;
}
return hight;
}
//在onDraw前調用
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width=0, hight=0;
width = this.getwidth(widthMeasureSpec);
hight = this.getheight(heightMeasureSpec);
this.setMeasuredDimension(width, hight);
}
// // 用於繪製界面上的內容,當界面顯示時調用
@Override
protected void onDraw(Canvas canvas) {// canvas畫布對象
super.onDraw(canvas);
// 創建筆 畫
Paint paint = new Paint();
paint.setColor(Color.BLUE);
// 畫圓
canvas.drawCircle(r, r, r, paint);
paint.setColor(Color.RED);
if (flag) {
canvas.drawCircle(r, r, 5, paint);
}
// 畫字
// 參數1:被繪製的字符串, 參數2,3:指字符串每一個字符的左下角座標
paint.setTextSize(30);// 設置文字大小
canvas.drawText(this.str, r, r, paint);
}
}
(1)一般情況重寫onMeasure()方法作用是爲了自定義View尺寸的規則,如果你的自定義View的尺寸是根據父控件行爲一致,就不需要重寫onMeasure()方法
1.
wrap--AT_MOST
fill--EXACTLY
固定值--EXACTLY
上邊是大家都知道的,但是一直很疑惑UNSPECIFIED什麼情況發生,今天測了下,發現在使用weigt時會調用,因爲此時定義的值爲0dp,這不就是UNSPECIFIED嘛!
specMode一共有三種可能:
MeasureSpec.EXACTLY:父視圖希望子視圖的大小應該是specSize中指定的。
MeasureSpec.AT_MOST:子視圖的大小最多是specSize中指定的值,也就是說不建議子視圖的大小超過specSize中給定的值。
MeasureSpec.UNSPECIFIED:我們可以隨意指定視圖的大小。
MATCH_PARENT對應於EXACTLY,WRAP_CONTENT對應於AT_MOST,其他情況也對應於EXACTLY,它和MATCH_PARENT的區別在於size值不一樣。