初识自定义View(一)

来源:互联网 发布:国际人工智能协会 编辑:程序博客网 时间:2024/05/17 02:21

首先来看一下都需要哪些步骤:
1.res/values下创建一个attrs.xml文件用来提供自定义属性
2.在构造方法中获得这些属性
3.重写onMeasure和onDraw方法
下面我们就来看一下具体是怎么一步步来的;
我们来创建一个名为my_first_attrs的xml文件

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="MyFirstView">        <attr name="textColor" format="color"></attr>        <attr name="text" format="string"></attr>        <attr name="textSize" format="dimension"></attr>    </declare-styleable></resources>

这里面我们定义了三个属性,分别是字体颜色、文本内容和字体大小。
下面来看一下在构造方法中是怎么获取这些属性的,

//默认字体颜色    private static final int DEFAULT_TEXT_COLOR = 0x01;    //默认字体大小    private static final int DEFAULT_TEXT_SIZE = 12;    protected int mTextColor = DEFAULT_TEXT_COLOR;    protected int mTextSize = DEFAULT_TEXT_SIZE;    protected String mText;    protected Paint mPaint = new Paint();//画笔    protected Rect mBound;//文本区域

首先定义了一些常量,包括有默认的字体颜色和字体大小,文本内容,画笔以及文本内容的区域
接下来是三个构造方法

public MyFirstView(Context context) {        this(context, null);    }    public MyFirstView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public MyFirstView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        //获取属性        final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MyFirstView);        mText = a.getString(R.styleable.MyFirstView_text);        mTextColor = a.getColor(R.styleable.MyFirstView_textColor, DEFAULT_TEXT_COLOR);        mTextSize = (int) a.getDimension(R.styleable.MyFirstView_textSize, DEFAULT_TEXT_SIZE);        a.recycle();        //定义画笔属性        mPaint.setTextSize(mTextSize);//字体大小        mBound = new Rect();        mPaint.getTextBounds(mText, 0, mText.length(), mBound);//计算文本区域    }
在构造方法中通过TypedArray来获取自定义的一些属性值,并对文本内容所占区域进行一个计算。剩下的就是就是重写onDraw方法了
@Override    protected void onDraw(Canvas canvas) {        mPaint.setColor(Color.BLUE);//画布颜色        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);//left top right bottom        mPaint.setColor(mTextColor);//文字颜色        canvas.drawText(mText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);       }
为了让效果看起来更明显,我们在这里首先给画布定义了一个颜色值,并绘制。到此,我们算是初步完成了自定义View,然而,当你给控件的宽高设置wrap_content的时候会发现填充整个屏幕,这是因为我们没有重写onMeasure方法,接下来我们来看看onMeasure里面需要写些什么。在重写onMeasure之前,我们先了解一下onMeasure中常用的一些方法和属性,MeasureSpec.getMode()方法返回的是宽高的模式,有3中模式EXACTLY:一般是指明确了控件的大小,一般是设置有固定的宽高或者是match_parentAT_MOST:一般是指最大可以占用的空间,一般是设置wrap_contentUNSPECIFIED:这个模式很少用到,具体的我也不太清楚。。。
 @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        int width = 0;        int height = 0;        if (widthMode == MeasureSpec.EXACTLY) {            width = getPaddingLeft() + widthSize + getPaddingRight();        } else {            width = getPaddingLeft() + mBound.width() + getPaddingRight();        }        if (heightMode == MeasureSpec.UNSPECIFIED) {            height = getPaddingTop() + heightSize + getPaddingBottom();        } else {            height = getPaddingTop() + mBound.height() + getPaddingBottom();        }        setMeasuredDimension(width, height);    }

这个就是我们用来重新测量控件大小的方法,如果是设置的wrap_content的属性,我们通过paddingLeft+文本区域宽+paddingRight之和赋值给控件的宽度,同理用来测量控件的高度,最后调用setMeasuredDimension(width, height);方法就可以了

源码下载

0 0
原创粉丝点击