Android自定义View之Canvas绘图

Canvas为绘图提供了以下几个非常有用的方法:

  • Canvas.save()

  • Canvas.restore()

  • Canvas.translate()

  • Canvas.rotate()

 

Canvas.save(),字面理解为保存画布,类似于photoshop的图层,保存之后的操作类似于在新图层上作画。

Canvas.restore(),类似于图层合并的操作,作用是将save()之后绘制的图像与save()之前的图像合并。

Canvas.translate()Canvas是基于坐标进行绘图,这一方法的作用就是将坐标原点平移,先看一下原坐标:

若我们把黄色区域看作View画布,则坐标轴如图所示,xy箭头所指方向即为坐标轴的正向,translate(float x,float y)传入的两个参数就是新的坐标原点的坐标值。

Canvas.rotate(),与translate()类似,这一方法是旋转画布,需传入旋转角度,原点坐标xy三个参数。Canvas.rotate(45,0,0)的效果如下:

使用:

新建一个类ClockView继承View,重写onDraw()方法,然后在布局文件中引用就可以了。

 

案例一:

public class ClockView extends View {
    public ClockView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        float w = getWidth();
        float h = getHeight();
        
        /*画出外部圆盘*/
        Paint paintCircle=new Paint();      
        paintCircle.setStyle(Paint.Style.STROKE);
        paintCircle.setAntiAlias(true);
        paintCircle.setStrokeWidth(5);
        canvas.drawCircle(w /2, h /2, w /2,paintCircle);

       /* 画出表盘内刻度*/
        Paint paintDegree=new Paint();
        paintDegree.setStrokeWidth(3);
        for (int i=0;i<12;i++){
            if (i==0||i==3||i==6||i==9){
                paintDegree.setStrokeWidth(8);
                paintDegree.setTextSize(40);
                canvas.drawLine(w/2,h/2-w/2,w/2,h/2-w/2+90,paintDegree);
                String degree=String.valueOf(i);
                canvas.drawText(degree,w/2-paintDegree.measureText(degree)/2,h/2-w/2+110,paintDegree);
            }else{
                paintDegree.setStrokeWidth(3);
                paintDegree.setTextSize(25);
                canvas.drawLine(w/2,h/2-w/2,w/2,h/2-w/2+60,paintDegree);
                String degree=String.valueOf(i);
                canvas.drawText(degree,w/2-paintDegree.measureText(degree)/2,h/2-w/2+80,paintDegree);
            }
            canvas.rotate(30,w/2,h/2);      //旋转画布  每绘制一条线旋转一次画布,每次转30°
        }
        canvas.save();

        /*画出时针和分针*/
        Paint paintHour=new Paint();
        paintHour.setStrokeWidth(20);
        Paint paintMin=new Paint();
        paintMin.setStrokeWidth(10);
        canvas.translate(w/2,h/2);  //原点移动至圆心
        canvas.drawLine(0,0,100,100,paintHour);
        canvas.drawLine(0,0,0,-200,paintMin);
        canvas.restore();
    }
}
布局文件:

<com.example.y.study.MyView
    android:layout_centerInParent="true"
    android:layout_width="350dp"
    android:layout_height="360dp" />

效果如图:

 


案例二:


public class PeopleView extends View {
    public PeopleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        float w=getWidth();
        float h=getHeight();

        Paint paint=new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(3);
        canvas.drawCircle(w/2,h/4,h/8,paint);
        canvas.save();
        canvas.translate(w/2,3*h/8);
        canvas.drawLine(0,0,0,h/4,paint);
        canvas.drawLine(-w/4,h/16,w/4,h/16,paint);
        canvas.restore();       //此方法需在save()之后调用,因为它是将save()之后的绘图与save()之前合并

        // 如果没有save()操作,translate()和rotate()方法将基于上一次移动进行移动或旋转
        canvas.translate(w/2,5*h/8);
        canvas.drawLine(0,0,-h/8,h/4,paint);
        canvas.drawLine(0,0,h/8,h/4,paint);
    }
}

布局文件:

<com.example.y.study.PeopleView
    android:layout_centerInParent="true"
    android:layout_width="350dp"
    android:layout_height="350dp" />

效果如图:

猜你喜欢

转载自blog.csdn.net/yforyoung/article/details/80010964