自定义View(一)

  • 添加attr.xml,并在构造器中使用
public ProgressBarView(Context context, AttributeSet attrs) {
        super(context,attrs);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.progressbar);
        paintBold = typedArray.getDimensionPixelSize(R.styleable.progressbar_paintBold,10);
        linelengeth = typedArray.getDimensionPixelSize(R.styleable.progressbar_linelength,25);
        linenumber = typedArray.getInteger(R.styleable.progressbar_linenumber,20);
        backgroundColor = typedArray.getColor(R.styleable.progressbar_backgroundColor, Color.GRAY);
        beforeColor = typedArray.getColor(R.styleable.progressbar_beforeColor,Color.YELLOW);
        textColor = typedArray.getColor(R.styleable.progressbar_textColor,Color.BLACK);
        max = typedArray.getInteger(R.styleable.progressbar_max,100);
    //回收对象
        typedArray.recycle();
    }
  • 初始化Paint
    
        backgroundPaint = new Paint();
        backgroundPaint.setColor(backgroundColor);
        backgroundPaint.setStrokeWidth(paintBold);
//        设置结合处样式,Round为圆弧,Miter为锐角,Bevel为直线
        backgroundPaint.setStrokeJoin(Paint.Join.ROUND);
//        设置笔刷样式
        backgroundPaint.setStrokeCap(Paint.Cap.ROUND);
//        抗锯齿
        backgroundPaint.setAntiAlias(true);
  • 重写onMeasure
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        width = getSize(100,widthMeasureSpec);
        height = getSize(100,heightMeasureSpec);

    }

    public int getSize(int defaultSize,int measureSpec){
        int size = defaultSize;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        switch (specMode){
            case MeasureSpec.UNSPECIFIED:
                size = defaultSize;
                break;
            case MeasureSpec.AT_MOST:
                size = specSize;
                break;
            case MeasureSpec.EXACTLY:
                size = specSize;
                break;
        }
        return size;
    }
  • 重写onDraw
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int x = width/2;
        int y = height/2;
        int r = x-5;
        for (int i = 0;i0;count--){
            canvas.drawLine(x,y-r,x,y-r+linelengeth,beforePaint);
            canvas.rotate(360/linenumber,x,y);
        }
   } 
  • 调用invalidate()或postInvalidateDelayed()进行页面重绘,重绘时只调用onDraw方法,postInvalidateDelayed()方法传入时间,即一定时间后重绘view。
  • canvas的save和restore方法:
    • save方法保存当前canvas的状态
    • restore恢复save方法保存的状态,比如在canvas旋转之前调用save方法保存canvas状态,旋转后调用restore方法状态恢复到save方法保存的状态,即不用在反向旋转canvas,类似于图层的概念。save把画布状态放进状态栈中,restore返回栈中最顶层的状态栈画布。
  • 当需要重绘的只是一个view里的一小部分,并不需要重绘其他部分,如钟表只用重绘指针并不用重绘表盘,可考虑建立两个view一个为表盘,一个是指针,然后用FrameLayout把两个view组合起来,重绘的时候只用重绘指针部分,个人觉得会提高性能。
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int x = ClockView.getCirleX()/2;
        int y = ClockView.getCirleY()/2;

        int r= x-5;
        initTime();
        if (hour>12) hour = hour-12;
        hourDegree = hour*30+minute/2;
        minDegree = minute*6+second/10;
        secDegree = second*6;

        canvas.save();
        canvas.rotate(secDegree,x,y);
        canvas.drawLine(x,y-r+scalelength,x,y,secondPaint);

        canvas.restore();
        canvas.save();
        canvas.rotate(minDegree,x,y);
        canvas.drawLine(x,y-r+scalelength*4,x,y,minPaint);
        canvas.restore();


        canvas.rotate(hourDegree,x,y);
        canvas.drawLine(x,y-r+scalelength*6,x,y,hourPaint);
        postInvalidateDelayed(1000);
    }

Demo地址https://github.com/liuchangjiang0119/CustomView

你可能感兴趣的:(自定义View(一))