自定义View(一) 初识自定义view

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/darling_R/article/details/54861805

转载请注明出处:http://blog.csdn.net/darling_R/article/details/54861805
本文出自:哎呀小嘿的博客

今天练习了一下自定义view,效果图如下:
这里写图片描述
那么就来先了解一下一些属性的类型,方便后面使用:string , integer , dimension , reference , color…
1. reference:参考某一资源ID。
2. color:颜色值。
3. boolean:布尔值。
4. dimension:尺寸值。
5. float:浮点值。
6. integer:整型值。
7. string:字符串。
8. fraction:百分数。
9. enum:枚举值。
10. flag:位或运算。

注意:
属性定义时可以指定多种类型值。
(1)属性定义:

<declare-styleable name = "名称">
<attr name = "background" format = "reference|color" />
</declare-styleable>

(2)属性使用:

<ImageView
    android:layout_width = "42dip" 
    android:layout_height = "42dip" 
    android:background = "@drawable/图片ID|#00FF00"/>

自定义view步骤可分为以下几步:

1。自定义属性
首先在res/value 文件夹下新建一个attrs.xml文件,在里面定义一些可以供用户自定义的一些属性。
例如,提取自定义控件的几个属性,分别为大圆的背景色,进度条颜色,进度条宽度,百分比字体大小,百分比字体颜色,圆的半径。

    <declare-styleable name="CirclePercentView">
        <attr name="circleBg" format="color" />
        <attr name="progressColor" format="color" />
        <attr name="progressWidth" format="dimension" />
        <attr name="percentSize" format="dimension" />
        <attr name="percentColor" format="color" />
        <attr name="radius" format="dimension" />
    </declare-styleable>

2。新建一个类MyTextView继承View,重写三个构造方法。
这里要注意一点,自动生成的构造方法,里面是 super(),要把前两个改成 this(context,null)和this(context,attrs,0);或者在每个构造方法里都初始化一下也行;

    public CirclePercentView(Context context) {
        this(context, null);
    }

    public CirclePercentView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CirclePercentView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

在第三个构造方法里面获取自定义的属性,在最后位置一定要记得调用 typedArray.recycle() 释放;

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CirclePercentView, defStyleAttr, 0);

        mCirColor = ta.getColor(R.styleable.CirclePercentView_circleBg, 0xff3d3d3d);//默认黑灰色

        mPerTextColor = ta.getColor(R.styleable.CirclePercentView_percentColor, 0xffff3030);
        mPerTextSize = ta.getDimensionPixelSize(R.styleable.CirclePercentView_percentSize, DensityUtils.sp2px(context, 14));

        mProWidth = ta.getDimensionPixelSize(R.styleable.CirclePercentView_progressWidth, DensityUtils.dp2px(context, 5));
        mProColor = ta.getColor(R.styleable.CirclePercentView_progressColor, 0xfff0f0f0);

        mRadius = ta.getDimensionPixelSize(R.styleable.CirclePercentView_radius, DensityUtils.dp2px(context, 100));

        ta.recycle();

紧接着,初始化一些所需要的画笔,便于后面绘制使用:

        mCirPaint = new Paint();
        mCirPaint.setColor(mCirColor);

        mPerPaint = new Paint();
        mPerPaint.setColor(mPerTextColor);
        mPerPaint.setTextSize(mPerTextSize);


        mProPaint = new Paint();
        mProPaint.setStyle(Paint.Style.STROKE);
        mProPaint.setColor(mProColor);
        mProPaint.setStrokeWidth(mProWidth);

        mBounds = new Rect();
        mRectF = new RectF();

3。这里就可以重写onMeasure了,计算自定义控件的宽高;

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureDimension(widthMeasureSpec), measureDimension(heightMeasureSpec));
    }

    private int measureDimension(int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        if (specMode == MeasureSpec.EXACTLY) {//指定宽高了
            result = specSize;
        } else {// 一般为WARP_CONTENT
            result = 2 * mRadius;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

准备工作做完了,就可以把控件内容画出来了
4,重写onDraw方法,

    @Override
    protected void onDraw(Canvas canvas) {
        //画背景圆
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, mRadius, mCirPaint);
        //画进度条
        mRectF.set(getWidth() / 2 - mRadius + mProWidth / 2, getHeight() / 2 - mRadius + mProWidth / 2, getWidth() / 2 + mRadius - mProWidth / 2, getHeight() / 2 + mRadius - mProWidth / 2);
        canvas.drawArc(mRectF, 270, 360 * mCurPercent / 100, false, mProPaint);
        //画百分比文本
        String text = mCurPercent + "%";
        mPerPaint.getTextBounds(text, 0, text.length(), mBounds);
        canvas.drawText(text, getWidth() / 2 - mBounds.width() / 2, getHeight() / 2 + mBounds.height() / 2, mPerPaint);

    }

到这里,自定义的一个view就算完事了,下面就可以调用了;
在xml布局文件里这样引用:

<!-- 注意添加下面第二行,cust:是名字,可以随便叫-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:cust="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context="com.yh.customviewone.MainActivity">
    <!--在这里引用attrs里面的属性名,设置属性值-->
    <com.yh.customviewone.CirclePercentView
        android:id="@+id/circleView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        cust:circleBg="#3d3d3d"
        cust:percentColor="#ff0000"
        cust:percentSize="50sp"
        cust:progressColor="#0efefe"
        cust:progressWidth="5dp"
        cust:radius="100dp" />
</LinearLayout>

ps:

<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>  

类似于生命全局变量一样,把共有的属性提取出来,在标签里引用就行,方便有多个自定义view时,重复多个属性,这样可以减少代码量

附上代码地址:https://github.com/XiaoHeia/CirclePercentView/tree/master

猜你喜欢

转载自blog.csdn.net/darling_R/article/details/54861805