1.在values文件夹下建立一个 attrs.xml文件
attrs.xml 中的format值如下
"reference" //引用
"color" //颜色
"boolean" //布尔值
"dimension" //尺寸值
"float" //浮点值
"integer" //整型值
"string" //字符串
"fraction" //百分数,比如200%
以下是构建的attrs.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="wide" format="float"></attr>
<attr name="height" format="float"></attr>
<attr name="titletextcolor" format="color"></attr>
<attr name="titletextsize" format="dimension"></attr>
<attr name="titletext" format="string"></attr>
<declare-styleable name="FirstView">
<attr name="wide" />
<attr name="height" />
<attr name="titletextcolor" />
<attr name="titletextsize" />
<attr name="titletext" />
</declare-styleable>
</resources>
由于在xml中的 attr是命名是不能重复的,所以一般定义在前面,而后 styleable再去调用,而这些属性,就是在调用自定义控件的时候,使用到的自定义属性,并且在自定义的类中进行调用使用
2.在布局文件中调用自定义的控件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:tw="http://schemas.android.com/apk/res/com.example.textmyview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<com.example.textmyview.myview.FirstView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tw:titletext="测试用的别认真"
tw:titletextcolor="@color/a_black"
tw:titletextsize="24sp" /> <!-- 这里的tw:titletextsize 就是自定义的属性 -->
</LinearLayout>
3.自定义类的编写
package com.example.textmyview.myview;
import com.example.textmyview.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
public class FirstView extends View{
private String titleText;//其中字体显示的值
private int titleSize;//字体大小
private int titleColor;//字体的颜色
private Paint mPaint;//画笔对象
private Rect mBound;//矩形框
private int mCount=0;
public FirstView(Context context){
this(context,null);
}
public FirstView(Context context, AttributeSet attrs) {
this(context, attrs,0);
// TODO Auto-generated constructor stub
}
public FirstView(Context context, AttributeSet attrs,int defStyle){
super(context, attrs, defStyle);
TypedArray a=context.obtainStyledAttributes(attrs,R.styleable.FirstView, defStyle, 0);//获取用户在xml中使用到的自定义属性
int count =a.getIndexCount();
for (int i = 0; i < count; i++) {
switch (a.getIndex(i)) {
case R.styleable.FirstView_titletext:
titleText=a.getString(R.styleable.FirstView_titletext);
break;
case R.styleable.FirstView_titletextsize:
titleSize=a.getDimensionPixelSize(R.styleable.FirstView_titletextsize, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
break;
case R.styleable.FirstView_titletextcolor:
titleColor=a.getColor(R.styleable.FirstView_titletextcolor, Color.BLUE);
break;
default:
break;
}
}
a.recycle();// 回收 TypedArray
mPaint=new Paint();
mPaint.setTextSize(titleSize);
mBound=new Rect();
mPaint.getTextBounds(titleText, 0, titleText.length(), mBound);
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
titleText=titleText+" 很矮 "+mCount;
// postInvalidate(); //postInvalidate()在工作者线程中被调用 刷新view
requestLayout(); //当被刷新的view需要重新刷新父类布局的时候进行调用
mCount++;
}
});
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
mPaint.setColor(Color.DKGRAY);
Log.e("", "getMeasuredWidth():"+getMeasuredWidth());//自定义view的宽度
Log.e("", "getMeasuredHeight()"+getMeasuredHeight());//自定义view的高度
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
mPaint.setColor(titleColor);
Log.e("", "getWidth() :"+(getWidth() ));//自定义view的宽度
Log.e("", "mBound.width() :"+(mBound.width() )); //画出的矩形的宽度
Log.e("", "getHeight() :"+(getHeight() ));//自定义view的高度
Log.e("", "mBound.height() :"+(mBound.height() ));//画出的矩形的高度
canvas.drawText(titleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int wideMode=MeasureSpec.getMode(widthMeasureSpec);
int wideSize=MeasureSpec.getSize(widthMeasureSpec);
int heightMode=MeasureSpec.getMode(heightMeasureSpec);
int heightSize=MeasureSpec.getSize(heightMeasureSpec);
int wide;
int height;
if(wideMode==MeasureSpec.EXACTLY){//判断是否是给了确定的值,或是 match_parent
wide=wideSize;
}else{
mPaint.setTextSize(titleSize);
mPaint.getTextBounds(titleText, 0, titleText.length(), mBound);//以 (0,0)为起点返回一个匹配当前的字符最小的矩形
wide=(int)(getPaddingLeft()+mBound.width()+getPaddingRight());
}
if(heightMode==MeasureSpec.EXACTLY){
height=heightSize;
}else{
mPaint.setTextSize(titleSize);
mPaint.getTextBounds(titleText, 0, titleText.length(), mBound);
height=(int)(getPaddingTop()+mBound.height()+getPaddingBottom());
}
setMeasuredDimension(wide, height);//设置view的宽高
}
}
到这里一个简单的自定义的view算是完成了
参考 http://blog.csdn.net/lmj623565791/article/details/24252901