Android自定义View流程

做Android项目也做了好久啦,自定义控件也用了不少,有用别人现成的,也有用自己写的,现在项目已经告一段落,今天我们就来聊一聊Android自定义View流程。

Android自定义,大致分为以下几步:

1、确定自定义View所要完成的功能;

2、确定所需要的属性;

3、在自定义View的构造方法中获取相应的属性;

4、重写onMeasure()方法;

5、重写onLayout()方法;

6、重写onDraw()方法

其中的第4、5步不是必须的。

下面我们根据一个例子,来说明一下,这几步是怎么起作用的。

1、确定自定义View所要完成的功能:我们来自定义一个MyTextView,效果基本上和普通的TextView一样。好了,第一步已经完成了;

2、确定所需要的属性:需要文本、颜色、字号,目前就这些吧,然后我们开始自定义属性,属性类型定义有什么不明白的可以参看:Android 自定义属性 attr format取值类型   这些属性我们应该放在res/values/attr.xml中:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="my_customer">
        <attr name="textSize" format="dimension"></attr>
        <attr name="text" format="string"></attr>
        <attr name="textColor" format="color"></attr>
    </declare-styleable>

</resources>

3、在构造方法中获取相应的属性:

	private String mText;
	private int mTextSize;
	private int mTextColor;
	private Paint mPaint;
	private Rect mBound;

	public MyCustomerView(Context context) {
		this(context, null);
		// TODO Auto-generated constructor stub
	}

	public MyCustomerView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
		// TODO Auto-generated constructor stub
	}

	public MyCustomerView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		// TODO Auto-generated constructor stub
		TypedArray array = context.getTheme().obtainStyledAttributes(attrs,
				R.styleable.my_customer, defStyleAttr, 0);
		int n = array.getIndexCount();
		for (int i = 0; i < n; i++) {
			int attr = array.getIndex(i);
			switch (attr) {
			case R.styleable.my_customer_text:// 文本
				mText = array.getString(attr);
				break;
			case R.styleable.my_customer_textColor:// 文本的颜色
				mTextColor = array.getColor(attr, 0xff000000);
				break;
			case R.styleable.my_customer_textSize:// 文本字号
				mTextSize = array.getDimensionPixelSize(attr, (int) TypedValue
						.applyDimension(TypedValue.COMPLEX_UNIT_PX, 12,
								getResources().getDisplayMetrics()));
				break;
			}
		}
		array.recycle();
		mPaint = new Paint();
		mPaint.setTextSize(mTextSize);
		mBound = new Rect();
		mPaint.getTextBounds(mText, 0, mText.length(), mBound);
	}

4、 重写 onMeasure()方法,这一步的目的是为了设置自定义View的宽高,如果自定义view属于ViewGroup,还会设置及测量子View的宽高:

<span style="white-space:pre">	</span>@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		int widthSize = MeasureSpec.getSize(widthMeasureSpec);
		int heightMode = MeasureSpec.getMode(heightMeasureSpec);
		int heightSize = MeasureSpec.getSize(heightMeasureSpec);

		int width;
		int height;
		if (widthMode == MeasureSpec.EXACTLY) {//确定值,定值\match_parent
			width = widthSize;
		} else {//wrap_content
			width = getPaddingLeft() + mBound.width() + getPaddingRight();
		}
		if (heightMode == MeasureSpec.EXACTLY) {//确定值,定值\match_parent
			height = heightSize;
		} else {//wrap_content
			height = getPaddingTop() + mBound.height() + getPaddingBottom();
		}
		setMeasuredDimension(width, height);

	}


简单介绍下三种测量模式:

EXACTLY:表示设置了精确的值,一般当View设置其宽、高为精确值、match_parent时,为EXACTLY;

AT_MOST:表示子布局被限制在一个最大值内,一般当View设置其宽、高为wrap_content时,为AT_MOST;

UNSPECIFIED:表示子布局想要多大就多大,一般出现在AadapterView的item的heightMode中、ScrollView的childView的heightMode中;此种模式比较少见。

5、重写onLayout()方法:目前这个自定义View还没有用到,ViewGroup中子View的布局方法,用于放置子View的位置,放置子View很简单,只需要重写onLayout方法就可以啦,然后获取子View的实例,调用子View的layout方法实现布局。

6、重写onDraw()方法:

@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		mPaint.setColor(0xff00ff00);
		canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);

		mPaint.setColor(mTextColor);
		canvas.drawText(mText, getWidth() / 2 - mBound.width() / 2, getHeight()
				/ 2 + mBound.height() / 2, mPaint);
	}


OK,目前位置,已经结束啦。


项目下载


你可能感兴趣的:(android,自定义view)