自定义View的实战学习(一)

先看效果

 观察效果图,分为底层弧(黑色),顶层弧(青色)和文本,顶层颜色的填充会随着文本的变化而变化

一、创建自定义View

继承View,添加构造函数

public class StepView extends View {
    public StepView(Context context) {
        super(context);
    }

    public StepView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public StepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public StepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
}

可以看到,自定义View中有四个构造函数

1、public View(Context context)  可以在代码中初始化自定义的View
2、public View(Context context, @Nullable AttributeSet attrs)可以在布局文件中使用自定义的View
3、public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr)在布局文件中使用Style属性时
4、public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)仅在defStyleAttr为0或defStyleAttr不为0但Theme中没有为defStyleAttr属性赋值时起作用

二、创建与使用自定义属性

需要自定义底层弧的颜色,顶层弧的颜色,弧的宽度、文本的颜色、文本的字体大小、最大值(样例中设置10000)和当前值(样例中设置6000)

1、在values文件夹下新建资源文件attrs
<resources>
    <declare-styleable name="StepView">
        <attr name="currentStep" format="integer" />
        <attr name="stepSize" format="dimension" />
        <attr name="maxStep" format="integer" />
        <attr name="stepTextColor" format="reference" />
        <attr name="arcSize" format="dimension" />
        <attr name="maxArcColor" format="reference" />
        <attr name="currentArcColor" format="reference" />
    </declare-styleable>
</resources>

format的值有很多种,需要根据自身的需要选择

属性说明
reference引用值
color颜色值
boolean布尔值
dimension尺寸值
float浮点值
integer整型值
string字符串
fraction百分数值
enum枚举
flag
2、在布局中使用自定义属性
<com.example.stepview.StepView
        android:id="@+id/sv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:arcSize="20sp"
        app:currentArcColor="@color/teal_200"
        app:currentStep="500"
        app:maxArcColor="@color/black"
        app:maxStep="700"
        app:stepSize="50sp"
        app:stepTextColor="@color/black" />

三、获取自定义属性的值

在布局文件中使用了自定义的属性,需要我们在View里面获取

1、检索属性信息,R.styleable后面跟着的是自定义View

 2、获取属性

arcSize = typedArray.getDimensionPixelSize(R.styleable.StepView_arcSize, 50);
maxArcColor = typedArray.getColor(R.styleable.StepView_maxArcColor, getResources().getColor(R.color.black));

根据属性的值类型来获取对应的值,比如在xml中设置了

app:arcSize="20sp"

需要用getDimensionPixelSize()来获取值

四、测量onMeasure()

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

 参数widthMeasureSpec和heightMeasureSpec是32位的数,前2位是模式,后30位是值。

模式:

1、AT_MOST:子元素至多达到指定大小的值,布局中指定的宽高为warp_content

2、EXACTLY:父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小,布局中指定的宽高为match_parent或者是固定的值

3、UNSPECIFIED:父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小

所以如果模式是AT_MOST的话需要进行处理

   // 如果设置了宽高为warp_content,给它一个默认的宽高
        if (widthMode == MeasureSpec.AT_MOST) {
            width = 100;
        }

        if (heightMode == MeasureSpec.AT_MOST) {
            height = 100;
        }

        int a = Math.min(width, height);
        setMeasuredDimension(a, a);

五、绘制onDraw()

1、初始化画笔

需要用到三个画笔,分别画底层弧、顶层弧和文字

顶层弧的画笔初始化:

        mUpPaint = new Paint();
        mUpPaint.setColor(maxArcColor); // 画笔颜色
        mUpPaint.setStrokeWidth(arcSize); // 画笔宽度,即弧的宽度
        mUpPaint.setStyle(Paint.Style.STROKE); // 画笔样式选择描边
        mUpPaint.setStrokeCap(Paint.Cap.ROUND); // 笔画的样式,为笔划突出为半圆,中心位于路径的末端
        mUpPaint.setAntiAlias(true); //抗锯齿

文本画笔:

        mTextPaint = new Paint();
        mTextPaint.setColor(stepTextColor);
        mTextPaint.setTextSize(stepSize);
        mTextPaint.setAntiAlias(true);
2、 画底层弧

需要用到Canvas,Canvas提供了很多方法,画圆,画文字等等,这里需要画一个弧,选择drawArc(RectF oval,float startAngle,float sweepAngle,boolean useCenter,Panit paint)

参数说明:

oval:用于定义圆弧形状和大小的椭圆形边界,new的时候入参左、上、右、下的值,给定一个区域绘制

startAngle:圆弧开始的起始角度

sweepAngle:顺时针测量的扫描角度

useCenter:如果为true,则将椭圆的中心包括在圆弧中

paint:画笔

      // 画底层弧
        RectF rectF = new RectF(arcSize, arcSize, getWidth() - arcSize, getHeight());
        canvas.drawArc(rectF, 135, 270, false, mUpPaint);
3、画顶层弧

顶层和底层的一样

// 画顶层弧
float x = ((float) currentStep / maxStep) * 270;
canvas.drawArc(rectF, 135, x, false, mDownPaint);
4、画文字

使用canvas提供的drwaText(String text,float x,float y,Paint paint)

参数说明:

text:要绘制的文本

x:绘制的文本原点的x坐标

y:正在绘制的文本的基线的y坐标

paint:画笔

注意:y的值是基线的坐标,不是文字底部的坐标,baseline到top的值是负数,所以y的值应该是getHeight/2 +(bottom-top)/2-bottom

        // 画文字
        Rect rect = new Rect();
        mTextPaint.getTextBounds(String.valueOf(currentStep), 0, String.valueOf(currentStep).length(), rect);
        int dx = getWidth() / 2 - rect.width() / 2;

        Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();
        int dy = getHeight() / 2 + (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
        canvas.drawText(String.valueOf(currentStep), dx, dy, mTextPaint);

 六、属性动画

在自定义View中开放一个方法,可以让外面把值传过来

    public void setCurrentStep(int currentStep) {
        this.currentStep = currentStep;

        invalidate();
    }

 调用了invalidate(),会走到onDraw方法里,重新绘制

        ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 6000);// 开始值和结束值
        valueAnimator.setDuration(5000);// 动画时长
        valueAnimator.setInterpolator(new DecelerateInterpolator());// 设置插值器
        // 监听
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int animatedValue = (int) animation.getAnimatedValue();

                sv.setCurrentStep(animatedValue);
            }
        });
        valueAnimator.start();// 开始执行

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值