1. 程式人生 > >Android 自定義控制元件-Canvas和Paint繪圖詳解-手把手帶你繪製一個時鐘.

Android 自定義控制元件-Canvas和Paint繪圖詳解-手把手帶你繪製一個時鐘.

,Android - Paint基礎

在自定義控制元件時,經常需要使用canvas、paint等,在canvas類中,繪畫基本都是靠drawXXX()方法來完成的,在這些方法中,很多時候都需要用到paint型別的引數,
Paint作為一個非常重要的元素,功能也是非常強大的,這裡簡單列舉一些它的屬性和對應的功能.

  • setAntiAlias() //設定畫筆的鋸齒效果
  • setColor() //設定畫筆的顏色
  • setARGB() //設定畫筆的ARGB值
  • setAlpha() //設定畫筆的Alpha值
  • setTextSize() //設定字型的的大小
  • setStyle() //設定畫筆的風格(實心或者是空心)
  • setStrokeWidth() //設定空心邊框的寬度.

  • 正是由於畫筆的功能不一樣,再結合各種不同的繪圖api,這樣任意的組合就可以實現不同的繪圖效果.
    例如:
 mPaint = new Paint();
        mPaint.setColor(getResources().getColor(R.color.colorAccent));
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth
(10); mPaint.setTextSize(100);

以上就是關於Paint類的一個簡單的介紹,更多的介紹可以參考Google的官方文件

2,Android - Canvas基礎

具體的看程式碼

 canvas.drawPoint(100,100,mPaint);
        //繪製一條直線
        canvas.drawLine(150,150,150,300,mPaint);
        float [] pts = {
                300,300,300,400,
                300,400,400,400,
                400,400,400
,500 }; //繪製多條直線 canvas.drawLines(pts,mPaint); //繪製一個矩形 RectF rectF = new RectF(500,100,600,300); canvas.drawRect(rectF,mPaint); //繪製圓角矩形 RectF rectF2 = new RectF(700,100,900,300); canvas.drawRoundRect(rectF2,50,50,mPaint); //繪製一個圓 canvas.drawCircle(600,600,100,mPaint); //繪製一個扇形 RectF rectFArc = new RectF(300,800,500,1000); canvas.drawArc(rectFArc,0,270,true,mPaint); mPaint.setStyle(Paint.Style.STROKE); //繪製一個弧形 RectF rectFArc2 = new RectF(300,1100,500,1300); canvas.drawArc(rectFArc2,0,270,false,mPaint); //繪製橢圓 外接矩形 也就就是該橢圓為矩形的內接橢圓 RectF rectFArOval = new RectF(520,1100,720,1400); canvas.drawOval(rectFArOval,mPaint); //繪製文字 canvas.drawText("hello",100,100,mPaint); Path path = new Path(); path.moveTo(100,400); path.lineTo(200,500); path.lineTo(100,600); path.lineTo(50,700); canvas.drawPath(path,mPaint);

3,簡單例項,繪製一個時鐘

先看圖
這裡寫圖片描述

效果就如上圖所示,那這樣的效果是怎麼實現的呢?這就需要用到Canvas和Paint的相關知識了.

Canvas作為繪製圖形的直接物件,它提供了以下幾個非常有用發方法.
1. canvas.save() : 儲存畫布,它的作用是將之前的所有已經繪製的影象儲存起來,讓後續的操作就好像在一個新的圖層上,操作一樣.
2. canvas.restore() :可以理解和PhotosShop中的合併圖層操作.它的作用是我們在save之後繪製的所有影象與save之前的影象進行合併.
3. canvas.translate():畫布平移,就是將畫布的座標原點移動到你指定的位置.
4. canvas,rotate():畫布翻轉,.就是將座標系翻轉了一定的角度.
理解了以上幾個方法,那麼我們就可以開始繪製我們的時鐘了,先來分析下要繪製的這個圖形,.我們可以分成4個步驟.

  1. 繪製儀表盤–外面的那個大圓形
  2. 刻度線-
  3. 刻度值
  4. 指標

在這個例項中,第一步繪製錶盤,這個挺簡單的,只要呼叫canvas,drawCircle()來繪製一個圓盤就可以了,圓心位置和半徑按照自己的需要來確定,
程式碼如下:

 mWidth = getMeasuredWidth()-100;
        mHeight = getMeasuredHeight()-100;
        //首先繪製一個大圓盤
        Paint paintCircle = new Paint();
        paintCircle.setStyle(Paint.Style.STROKE);
        paintCircle.setAntiAlias(true);
        paintCircle.setStrokeWidth(5);
        canvas.drawCircle(mWidth/2,mHeight/2,mWidth/2,paintCircle);

第二部繪製刻度線和刻度值,我們可以將一個圓分成120根刻度線,每兩根刻度線之間的角度為3度,我們只要每繪製好一根線後,我們就畫布旋轉3度,程式碼如下:

//繪製刻度
        Paint paintDegree = new Paint();
        paintDegree.setStrokeWidth(3);
        for (int i = 0 ;i<120 ;i++){
            //大點,12點 3點 6點 9點
            if (i == 0 || i == 30 || i==60 || i ==90){
                paintDegree.setStrokeWidth(12);
                paintDegree.setTextSize(60);
                canvas.drawLine(mWidth/2,mHeight/2-mWidth/2,mWidth/2,mHeight/2-mWidth/2+80,paintDegree);
                String degree = String.valueOf(i/10);
                if (i == 0){
                    degree = "12";
                }
                canvas.drawText(degree,mWidth/2-paintDegree.measureText(degree)/2,mHeight/2-mWidth/2+150,paintDegree);
            }else if (i % 10 == 0){////整點
                paintDegree.setStrokeWidth(9);
                paintDegree.setTextSize(60);
                String degree = String.valueOf(i/10);
                canvas.drawText(degree,mWidth/2-paintDegree.measureText(degree)/2,mHeight/2-mWidth/2+140,paintDegree);
                canvas.drawLine(mWidth/2,mHeight/2-mWidth/2,mWidth/2,mHeight/2-mWidth/2+60,paintDegree);
            }else if (i % 5 == 0){
                paintDegree.setStrokeWidth(6);
                paintDegree.setTextSize(20);
                canvas.drawLine(mWidth/2,mHeight/2-mWidth/2,mWidth/2,mHeight/2-mWidth/2+40,paintDegree);
            }
            else{
                paintDegree.setStrokeWidth(3);
                paintDegree.setTextSize(20);
                canvas.drawLine(mWidth/2,mHeight/2-mWidth/2,mWidth/2,mHeight/2-mWidth/2+20,paintDegree);
            }
            //每次繪製完成後將畫布旋轉3度
            canvas.rotate(3, mWidth / 2, mHeight / 2);
        }

最後在繪製指標:

 //儲存錶盤和刻度的畫布
        canvas.save();
        //繪製指標
        Paint paintPoint = new Paint();
        Paint paintHouse = new Paint();
        paintHouse.setStrokeWidth(15);
        Paint paintMinute = new Paint();
        paintMinute.setStrokeWidth(10);
        Paint paintSecond = new Paint();
        paintSecond.setStrokeWidth(8);

        //將畫布的起點座標移動到圓心位置
        canvas.translate(mWidth/2,mHeight/2);
        canvas.drawCircle(0,0,15,paintPoint);
        canvas.drawLine(0,0,0,-100,paintHouse);
        canvas.drawLine(0,0,0,180,paintMinute);
        canvas.drawLine(0,0,100,250,paintSecond);
        //合併圖層
        canvas.restore();

全部的程式碼如下:

package com.example.administrator.myscrollview.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by Administrator on 2016/9/29.
 */
public class ClockView extends View {
    private int mWidth,mHeight;
    public ClockView(Context context) {
        this(context,null);
    }

    public ClockView(Context context, AttributeSet attrs) {
        this(context, attrs,-1);
    }

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

    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(50,0);
        mWidth = getMeasuredWidth()-100;
        mHeight = getMeasuredHeight()-100;
        //首先繪製一個大圓盤
        Paint paintCircle = new Paint();
        paintCircle.setStyle(Paint.Style.STROKE);
        paintCircle.setAntiAlias(true);
        paintCircle.setStrokeWidth(5);
        canvas.drawCircle(mWidth/2,mHeight/2,mWidth/2,paintCircle);
        //繪製刻度
        Paint paintDegree = new Paint();
        paintDegree.setStrokeWidth(3);
        for (int i = 0 ;i<120 ;i++){
            //大點,12點 3點 6點 9點
            if (i == 0 || i == 30 || i==60 || i ==90){
                paintDegree.setStrokeWidth(12);
                paintDegree.setTextSize(60);
                canvas.drawLine(mWidth/2,mHeight/2-mWidth/2,mWidth/2,mHeight/2-mWidth/2+80,paintDegree);
                String degree = String.valueOf(i/10);
                if (i == 0){
                    degree = "12";
                }
                canvas.drawText(degree,mWidth/2-paintDegree.measureText(degree)/2,mHeight/2-mWidth/2+150,paintDegree);
            }else if (i % 10 == 0){////整點
                paintDegree.setStrokeWidth(9);
                paintDegree.setTextSize(60);
                String degree = String.valueOf(i/10);
                canvas.drawText(degree,mWidth/2-paintDegree.measureText(degree)/2,mHeight/2-mWidth/2+140,paintDegree);
                canvas.drawLine(mWidth/2,mHeight/2-mWidth/2,mWidth/2,mHeight/2-mWidth/2+60,paintDegree);
            }else if (i % 5 == 0){
                paintDegree.setStrokeWidth(6);
                paintDegree.setTextSize(20);
                canvas.drawLine(mWidth/2,mHeight/2-mWidth/2,mWidth/2,mHeight/2-mWidth/2+40,paintDegree);
            }
            else{
                paintDegree.setStrokeWidth(3);
                paintDegree.setTextSize(20);
                canvas.drawLine(mWidth/2,mHeight/2-mWidth/2,mWidth/2,mHeight/2-mWidth/2+20,paintDegree);
            }
            //每次繪製完成後將畫布旋轉3度
            canvas.rotate(3, mWidth / 2, mHeight / 2);
        }
        //儲存錶盤和刻度的畫布
        canvas.save();
        //繪製指標
        Paint paintPoint = new Paint();
        Paint paintHouse = new Paint();
        paintHouse.setStrokeWidth(15);
        Paint paintMinute = new Paint();
        paintMinute.setStrokeWidth(10);
        Paint paintSecond = new Paint();
        paintSecond.setStrokeWidth(8);

        //將畫布的起點座標移動到圓心位置
        canvas.translate(mWidth/2,mHeight/2);
        canvas.drawCircle(0,0,15,paintPoint);
        canvas.drawLine(0,0,0,-100,paintHouse);
        canvas.drawLine(0,0,0,180,paintMinute);
        canvas.drawLine(0,0,100,250,paintSecond);
        //合併圖層
        canvas.restore();
    }
}

效果這裡寫圖片描述

到這,本文就結束了,希望對大家有所幫助,謝謝.