Android自定义view之自己真正意义上的自定义view

      之前的自定义view文章也写了几篇了,但是也一直是局限于搞懂系统API如何使用等,还是没有真正的实践过,今天这篇文章算是自己真正意义上的第一次自定义view,就是做了一个常见的尺子效果的半成品(不要打我),毕竟有些东西还是不那么会,以后肯定会完善的,由于手势触摸部分还不是那么会,所以我就直接用了动画来做尺子的滑动效果了,请见谅。

      下面先看效果图:

上面的绿线所在位置,就是当前刻度所在位置,就是33,下面尺子的每一个间隔都代表1,每两个长线之间是10,上面绿色的数字代表现在刻度值,整体就是这么简单。

      我画的这个尺子结构也很明显 ,就三部分,第一部分就是当前刻度位置,第二部分就是刻度值绿色数值的位置,第三部分就是下面的标尺。其实第一部分和第二部分位置都是固定的了,我取的就是屏幕中央的位置,第三部分刻度尺部分稍微复杂一些了,但是现在我做的效率不是特别高,其实就是在尺子在根据动画滚动至指定位置处时候,动画执行一次,尺子就会绘制一次,并且每次尺子绘制是完全绘制的,因为尺子是有总长度的,尺子中的文字都是用drawText绘制文字,尺子的线自然也是drawLine,其实说白了就是用了这两个方法,一个绘制文字一个绘制线,仅此而已。下面直接看代码啦:          

/**
 * 尺子view(算是第一个真正意义上的自定义view吧)
 * Created by hexiaopang on 2018/4/16 11:55.
 */
public class RulerView extends View {
    private Paint paintText;//文字画笔
    private Paint paintLine;//线的画笔
    private int count;
    private int x, y;
    private int currentValue;
    private Canvas canvas;

    public RulerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        count = 100;
        currentValue = 20;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        this.canvas = canvas;
        if (paintText == null || paintLine == null) {
            paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
            paintLine = new Paint(Paint.ANTI_ALIAS_FLAG);
            paintText.setTextSize(20);
            paintText.setStrokeWidth(5);
            paintLine.setStrokeWidth(5);
            paintText.setColor(Color.GREEN);
            paintLine.setColor(Color.GRAY);
            paintText.setStrokeCap(Paint.Cap.ROUND);
            paintLine.setStrokeCap(Paint.Cap.ROUND);
            paintLine.setTextSize(20);
        }
        //绘制刻度的基线,这个也必须在每次ondraw时候绘制,否则也会无效
        canvas.drawLine(getWidth() / 2 - currentValue * 20, getHeight() / 2, getWidth() / 2 + count * 20, getHeight() / 2, paintLine);
        canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2, getHeight() / 2 + 100, paintText);
        drawRule();
    }

    //根据刻度总数以及起始坐标绘制尺子(起始点起始是一个关键,然后让尺子滚动至起始点就好了),现在一个刻度代表1,如果是想要代表0.1则需要有所修改
    private void drawRule() {
        canvas.drawText(String.valueOf(currentValue), getWidth() / 2, getHeight() / 2 - 10, paintText);
        for (int i = 0; i < count; i++) {
            //每一个刻度的横坐标
            x = getWidth() / 2 + i * 20 - currentValue * 20;
            //每一个刻度的纵坐标
            if (i % 10 == 0) {
                //如果能被10整除,则代表是到了整数部分,则竖线需要加长
                y = getHeight() / 2 + 50;
                //如果能被10整除,则还需要添加标尺数字
                canvas.drawText(String.valueOf(i), x, y + 10, paintLine);
            } else {
                //否则只是普通的值
                y = getHeight() / 2 + 30;
            }
            canvas.drawLine(x, getHeight() / 2, x, y, paintLine);
        }
    }

    //上面的方法能够使其一步到位,现在想做的是慢慢滚动过去,那就动画,但是动画是执行在谁身上呢?
    //总想在绘制完成之后,所以如果想要实现,那么就执行一个ValueAnimator动画,不断更新数值,那么就不断的绘制吧
    public void doAnim(int currentValue) {
        ObjectAnimator objectAnimator = ObjectAnimator.ofInt(this, "currentValue", 0, currentValue);
        objectAnimator.setDuration(5000);
        objectAnimator.setInterpolator(new LinearInterpolator());
        objectAnimator.start();
    }

    //动画提供set方法
    public void setCurrentValue(int currentValue) {
        this.currentValue = currentValue;
        postInvalidate();
    }

    public int getCurrentValue() {
        return currentValue;
    }
}

        以上就是这个view的全部代码。onDraw方法里面绘制了,首先是对画笔进行初始化,设置了画笔的颜色,粗细以及绘制文字时候的大小,以及画线时候两端的形状展示(现在是椭圆),然后是绘制刻度基线,就是图中看到的那种横着灰色的线,然后是绘制刻度所在的位置线,就是那条竖着的绿色的线,方法drawRule()就是绘制具体的刻度的方法,该方法的第一行是绘制刻度所在位置的文字,就是上图中绿色的文字,下面的for循环真的是在绘制一个个的刻度,其实就是在drawline,drawline只要确定了线的起始点的坐标和结束点的坐标就可以绘制出来一条线了,另外因为我们画的是竖线,所以每一条线的起点和终点横坐标是相同的,终点的纵坐标就是起点y加上线的长度,上面我们绘制的当前刻度的绿线的起始点放在了屏幕中间,所以我们无论如何绘制刻度,都要保持,这个竖线在中间,所以当我们设置一个当前刻度时候,为了让绿线在中间,我们需要移动下面的刻度尺,让它的起始点往左移动,只有这样才能保证绿线在屏幕中间了,所以我们在drawRule方法里面的每一个刻度的横坐标是 x = getWidth() / 2 + i * 20 - currentValue * 20 这行代码,因为我们的绘制起点是在屏幕中间的位置处然后做变动,同时20指的是每两个刻度之间的物理间隔,而i指的是第几个刻度,后面减去的currentValue*20就是指当前这个点要向左平移多少距离,可以认为所有点的初始位置的x坐标都在屏幕中间,然后根据当前位置去向左平移位置了,x的部分就此结束,下来咱们看y,y其实很简单,起始点就是屏幕高度的中间,结束点就是起始点加上线长,有一个i % 10 == 0的判断,有这个判断是因为可以看到图中,每隔十个刻度就会有一条长一点的灰色线,普通的刻度就是短一点的灰色线,同时在长一点的灰色线那里还要标上文字刻度,就跟真的尺子似的。最后是doAnim则是启动动画,让尺子滑动至传进来的当前刻度那里,当然我们属性动画里面用的是自定义属性currentValue,所以我们也提供了setCurrentValue的方法,供属性动画调用,其实这个动画做的事情很简单,就是让一个int值从0变化至currentValue了,而我们的setCurrentValue方法也只是接收了currentValue,然后重新绘制界面的view而已了,由于currentValue一直在变,所以我们看到尺子一直在动。

       其实说来,这真的算是自己的第一个自定义view,当然写的很不好,有很多瑕疵,性能问题也要考虑,并且还不支持触摸滑动,当然这些后面我都会持续改进。

       好,以上就是本次的全部内容,有问题欢迎批评指正。

       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值