自定义控件01

对于Android自定义View是高手进阶的必经之路,所有准备在自定义View好好学习,自己学习参考的博客http://blog.csdn.net/lmj623565791/article/details/24252901 在此表示万分感谢

1、自定义View的属性,首先在res/values/  下建立一个attr.xml , 在里面定义我们的属性和声明我们的整个样式。

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

    <attr name="titleText" format="string" />
    <attr name="titleTextColor" format="color" />
    <attr name="titleTextSize" format="dimension" />

    <declare-styleable name="CustomTitleView">
        <attr name="titleText" />
        <attr name="titleTextColor" />
        <attr name="titleTextSize" />
    </declare-styleable>

</resources>
2、在View的构造方法中,获得我们的自定义的样式

public class CustomTitleView extends View {
    /**
     * 文本
     */
    private String mTitleText;
    /**
     * 文本的颜色
     */
    private int mTitleTextColor;
    /**
     * 文本的大小
     */
    private int mTitleTextSize;
    /**
     * 绘制时控制文本绘制的范围
     */
    private Rect mBound;
    private Paint mPaint;

    public CustomTitleView(Context context) {
        // 这里一定要改成this
        this(context, null);
    }

    public CustomTitleView(Context context, AttributeSet attrs) {
        // 这里一定要改成this
        this(context, attrs, 0);
    }

    public CustomTitleView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // 获得我们自定义的属性
        TypedArray obtainStyledAttributes = context.getTheme()
                .obtainStyledAttributes(attrs, R.styleable.CustomTitleView,
                        defStyle, 0);
        // 获取一共定义了多少个属性值
        int indexCount = obtainStyledAttributes.getIndexCount();
        // 遍历获得所需的属性值
        for (int i = 0; i < indexCount; i++) {
            // 获取对应属性值的对应下标
            int viewIndex = obtainStyledAttributes.getIndex(i);
            switch (viewIndex) {
            case R.styleable.CustomTitleView_titleText:
                mTitleText = obtainStyledAttributes.getString(viewIndex);
                break;
            case R.styleable.CustomTitleView_titleTextColor:
                // 默认颜色设置为黑色
                mTitleTextColor = obtainStyledAttributes.getColor(viewIndex,
                        Color.BLACK);
                break;
            case R.styleable.CustomTitleView_titleTextSize:
                // 默认设置为16sp,TypeValue也可以把sp转化为px
                mTitleTextSize = obtainStyledAttributes.getDimensionPixelSize(
                        viewIndex, (int) TypedValue.applyDimension(
                                TypedValue.COMPLEX_UNIT_SP, 16, getResources()
                                        .getDisplayMetrics()));
                break;

            default:
                break;
            }

        }
        obtainStyledAttributes.recycle();
        /**
         * 获得绘制文本的宽和高
         */
        mPaint = new Paint();
        mPaint.setTextSize(mTitleTextSize);
        mPaint.setColor(mTitleTextColor);
        mBound = new Rect();
        mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        <span style="color:#3366ff;">/*
         * onMeasure传入的widthMeasureSpec和heightMeasureSpec不是一般的尺寸数值,而是将模式和尺寸组合在一起的数值
         * 。 我们需要通过int mode = MeasureSpec.getMode(widthMeasureSpec)得到模式,用int
         * size = MeasureSpec.getSize(widthMeasureSpec)得到尺寸。
         * 
         * mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY,
         * MeasureSpec.AT_MOST。
         * 
         * MeasureSpec.EXACTLY是精确尺寸,
         * 当我们将控件的layout_width或layout_height指定为具体数值时如andorid
         * :layout_width="50dip", 或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。
         * 
         * MeasureSpec.AT_MOST是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时
         * , 控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,
         * size给出了父控件允许的最大尺寸。
         * 
         * MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式
         * 。
         */</span>
        int width = 0;
        int height = 0;
        /**
         * 设置宽度
         */
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        switch (specMode) {
        case MeasureSpec.EXACTLY:// 明确指定了
            width = getPaddingLeft() + getPaddingRight() + specSize;
            break;
        case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT
            width = getPaddingLeft() + getPaddingRight() + mBound.width();
            break;
        }

        /**
         * 设置高度
         */
        specMode = MeasureSpec.getMode(heightMeasureSpec);
        specSize = MeasureSpec.getSize(heightMeasureSpec);
        switch (specMode) {
        case MeasureSpec.EXACTLY:// 明确指定了
            height = getPaddingTop() + getPaddingBottom() + specSize;
            break;
        case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT
            height = getPaddingTop() + getPaddingBottom() + mBound.height();
            break;
        }
        //setMeasuredDimension(int, int)设置实际大小。
        setMeasuredDimension(width, height);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        mPaint.setColor(Color.BLUE);
       <span style="color:#3366ff;"> /**
         * getMeasuredWidth和getWidth的区别
         * getWidth 是布局中展示出来的宽度
         * getMeasuredWidth是全部的长度 包括隐藏的
         */</span>
        //绘制一个矩形
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);

        mPaint.setColor(mTitleTextColor);
       <span style="color:#3333ff;"> /*drawText()参数
                    理解好一个函数所需参数的具体含义,是用好一个函数的关键。canvas.drawText(String text, float x, float y, Paint paint)中有四个参数,
                    这四个参数都是表示其相对于所在View中的坐标,和屏幕坐标无关。其中text和paint较容易理解,下面重点介绍x和y的具体含义。
        float x:根据官方API上的解释,该参数表示text被画的起始x坐标。其实text被画的起始位置还与Paint有关,
        Paint的TextAlign属性决定了text相对于起始坐标x的相对位置。例如,TextAlign的默认属性为Paint.Align.LEFT,这是text就是从起始坐标x的右侧开始画起。*/</span>
        canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2,
                getHeight() / 2 + mBound.height() / 2, mPaint);
    }

}
3.修改下布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
   <span style="color:#ff0000;"> xmlns:app="http://schemas.android.com/apk/res/com.example.view01"</span>
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.view01.MainActivity" >

    <com.example.view01.CustomTitleView
        app:titleText="1233"
        android:padding="5dp"
        app:titleTextColor="#ff0000"
        app:titleTextSize="12sp"
        android:layout_height="100dp"
        android:layout_width="300dp"
         />

</RelativeLayout>

运行效果图



自己菜鸟一个,希望大家能给我指正错误,有什么不对的地方请见谅

你可能感兴趣的:(自定义控件01)