1. 程式人生 > >Android——Canvas(畫布)的使用

Android——Canvas(畫布)的使用

Canvas的一些基本方法:

Canvas():建立一個空的畫布,可以使用setBitmap()方法來設定繪製的具體畫布;

Canvas(Bitmap bitmap):以bitmap物件建立一個畫布,則將內容都繪製在bitmap上,bitmap不得為null;

Canvas(GL gl):在繪製3D效果時使用,與OpenGL有關;

drawColor:設定畫布的背景色;

setBitmap:設定具體的畫布;

clipRect:設定顯示區域,即設定裁剪區;

isOpaque:檢測是否支援透明;

rotate:旋轉畫布;

canvas.drawRect(RectF,Paint)方法用於畫矩形

,第一個引數為圖形顯示區域,第二個引數為畫筆,設定好圖形顯示區域Rect和畫筆Paint後,即可畫圖;

canvas.drawRoundRect(RectF, float, float, Paint) 方法用於畫圓角矩形,第一個引數為圖形顯示區域,第二個引數和第三個引數分別是水平圓角半徑和垂直圓角半徑。

canvas.drawLine(startX, startY, stopX, stopY, paint):前四個引數的型別均為float,最後一個引數型別為Paint。表示用畫筆paint從點(startX,startY)到點(stopX,stopY)畫一條直線;

canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint):第一個引數oval為RectF型別,即圓弧

顯示區域,startAngle和sweepAngle均為float型別,分別表示圓弧起始角度和圓弧度數,3點鐘方向為0度,useCenter設定是否顯示圓心,boolean型別,paint為畫筆;

canvas.drawCircle(float,float, float, Paint)方法用於畫圓,前兩個引數代表圓心座標,第三個引數為圓半徑,第四個引數是畫筆;

Rect(int left,int top,int right,int bottom)



left

          矩形左上角X座標值

top

          矩形左上角Y座標值

right

          矩形右下角X座標值

bottom

          矩形右下角Y座標值 

畫布的一般使用步驟:
建立一個自定義View 讓他繼承View,並建立他的兩個構造器,並:

  public MyView(Context context) {
        super(context);
    }
    public MyView(Context context, AttributeSet attrs) {   super(context, attrs);}

重寫裡面的onMeasure和onDraw方法,並在onMeasure方法中,得到自定義View的寬高:

 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);//寬
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);//高
        setMeasuredDimension(width, height);//設定得到的寬高
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        }

在佈局檔案中設定剛建立自定義View:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

<com.example.administrator.myviewdemo.widget.ProgressBarCircle//自定義View
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

</RelativeLayout>

開始繪畫,在構造器中建立一個新的畫筆物件,並對其進行屬性設定,然後在onDraw方法裡運用Canvas的方法繪畫即可。

例項

1.畫一個時鐘

佈局檔案

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

<com.example.administrator.myviewdemo.widget.ProgressBarCircle
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

</RelativeLayout>

自定義View

package com.example.administrator.myviewdemo.widget;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;

import java.util.Calendar;

/**
 * Created by Administrator on 2015/9/16.
 * 畫一個時鐘
 */
public class MyView extends View {
    private int width;
    private int height;
    private Paint mPaintLine;
    private Paint mPaintCircle;
    private Paint mPaintText;
    private Calendar mCalendar;
    private static final int NEED_INVALIDATE = 0x23;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case NEED_INVALIDATE:
                    mCalendar = Calendar.getInstance();//得到當前時間
                    invalidate();//告訴主執行緒重新繪製
                    handler.sendEmptyMessageDelayed(NEED_INVALIDATE, 1000);//1秒鐘傳送一次空訊息
                    break;
            }
        }
    };

    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaintText = new Paint();//對畫筆初始化
        mPaintText.setTextSize(30);//設定字型大小
        mPaintText.setColor(Color.BLACK);//設定畫筆顏色
        mPaintText.setTextAlign(Paint.Align.CENTER);//設定文字對齊方式
        mPaintLine = new Paint();
        mPaintLine.setColor(Color.RED);
        mPaintLine.setStrokeWidth(10);//設定畫筆寬度
        mPaintLine.setAntiAlias(true);
        mPaintCircle = new Paint();
        mPaintCircle.setColor(Color.GREEN);
        mPaintCircle.setStyle(Paint.Style.STROKE);//設定為空心的
        mPaintCircle.setStrokeWidth(10);
        mPaintLine.setAntiAlias(true);//設定抗鋸齒
        mCalendar = Calendar.getInstance();
        handler.sendEmptyMessage(NEED_INVALIDATE);

    }

    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//由主執行緒自動呼叫,只需在此繪製即可
        canvas.drawCircle(width / 2, height / 2, 180, mPaintCircle);
        canvas.drawCircle(width / 2, height / 2, 5, mPaintCircle);
        for (int i = 1; i <= 12; i++) {
            canvas.save();
            canvas.rotate(30 * i, width / 2, height / 2);
            canvas.drawText("" + i, width / 2, height / 2 - 140, mPaintText);
            canvas.drawLine(width / 2, height / 2 - 180, width / 2, height / 2 - 160, mPaintLine);
            canvas.restore();
        }
        //得到小時數、分鐘數、秒數
        int minute = mCalendar.get(Calendar.MINUTE);
        int hour = mCalendar.get(Calendar.HOUR);
        int second = mCalendar.get(Calendar.SECOND);
        float degree = minute / 60f * 360;
        canvas.save();
        canvas.rotate(degree, width / 2, height / 2);
        canvas.drawLine(width / 2, height / 2 - 120, width / 2, height / 2 + 10, mPaintLine);//畫分針
        canvas.restore();
        float hourDegree = (hour * 60 + minute) / (12f * 60) * 360;
        canvas.save();
        canvas.rotate(hourDegree, width / 2, height / 2);
        canvas.drawLine(width / 2, height / 2 - 100, width / 2, height / 2 + 5, mPaintLine);//畫時針
        canvas.restore();
        canvas.save();
        canvas.rotate(second * 6, width / 2, height / 2);//每秒旋轉6度
        canvas.drawLine(width / 2, height / 2 - 140, width / 2, height / 2 + 15, mPaintLine);//畫秒針
        canvas.restore();


    }
}

MainActivity

package com.example.administrator.myviewdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

}

2.Progressbar(1)

這裡寫圖片描述

package com.example.administrator.myviewdemo.widget;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by Administrator on 2015/9/16.
 */
public class ProgressBarCircle extends View {
    private int maxProgress=100;
    private int currentProgress;
    private int width;
    private int height;
    private Paint mPaintProgressMax;
    private Paint mPaintProgressCurrent;


    private static final int UPDATA_PROGRESS=0x28;
    private Paint mPaintText;
    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case UPDATA_PROGRESS:
                    if(currentProgress<100) {
                        currentProgress++;
                    }
                    invalidate();
                    handler.sendEmptyMessageDelayed(UPDATA_PROGRESS,500);
                    break;
            }
        }
    };
    public int getMaxProgress() {
        return maxProgress;
    }

    public void setMaxProgress(int maxProgress) {
        this.maxProgress = maxProgress;
    }

    public int getCurrentProgress() {
        return currentProgress;
    }

    public void setCurrentProgress(int currentProgress) {
        this.currentProgress = currentProgress;
    }

    public ProgressBarCircle(Context context) {
        super(context);
    }

    public ProgressBarCircle(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaintProgressMax=new Paint();
        mPaintProgressMax.setColor(Color.GRAY);
        mPaintProgressMax.setAntiAlias(true);
        mPaintProgressCurrent=new Paint();
        mPaintProgressCurrent.setColor(Color.GREEN);
        mPaintProgressCurrent.setAntiAlias(true);
        mPaintText=new Paint();
        mPaintText.setTextSize(100);
        mPaintText.setColor(Color.RED);
        mPaintText.setTextAlign(Paint.Align.CENTER);
        handler.sendEmptyMessage(UPDATA_PROGRESS);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width,height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(width/2,height/2,200,mPaintProgressMax);
        canvas.drawCircle(width/2,height/2,currentProgress*200f/maxProgress,mPaintProgressCurrent);
        canvas.drawText(currentProgress*100f/maxProgress+"%",width/2,height/2,mPaintText);

    }
}

2.Progressbar(2)

這裡寫程式碼片
自定義View

package com.example.administrator.myprogressbar2.widget;

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

/**
 * Created by Administrator on 2015/9/16.
 */
public class MyProgressBar extends View {
    private int width;
    private int height;
    private int maxProgress=100;
    private float currentProgress;

    private Paint mPaintrectangleMax;
    private Paint mPaintrectangleCurrent;
    private Paint mPaintText;
    public int getMaxProgress() {
        return maxProgress;
    }

    public void setMaxProgress(int maxProgress) {
        this.maxProgress = maxProgress;
    }

    public float getCurrentProgress() {
        return currentProgress;
    }

    public void setCurrentProgress(float currentProgress) {
        this.currentProgress = currentProgress;
        invalidate();
    }

    public MyProgressBar(Context context) {
        super(context);

    }

    public MyProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaintrectangleMax=new Paint();
        mPaintrectangleMax.setColor(Color.BLACK);
       mPaintrectangleMax.setStyle(Paint.Style.STROKE);
        mPaintrectangleMax.setTextAlign(Paint.Align.CENTER);
        mPaintrectangleCurrent=new Paint();
        mPaintrectangleCurrent.setColor(Color.GREEN);

        mPaintText=new Paint();
        mPaintText.setColor(Color.BLACK);
        mPaintText.setTextSize(50);
        mPaintText.setTextAlign(Paint.Align.CENTER);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width,height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawRect(60, 90, 180, 300, mPaintrectangleMax);// (60,90)長方形左上頂點。(180,300)右下頂點
//        canvas.drawLine(60,300-currentProgress*210f/maxProgress,180,300-currentProgress*210f/maxProgress,mPaintrectangleCurrent);
       canvas.drawRect(60,300-currentProgress*210/maxProgress,180,300,mPaintrectangleCurrent);
        canvas.drawText(currentProgress+"%",150,240,mPaintText);


    }
}

佈局檔案

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
    <Button
        android:id="@+id/btn_startdown"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="開始下載"/>
<com.example.administrator.myprogressbar2.widget.MyProgressBar
    android:id="@+id/progressbar2"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

</RelativeLayout>

MainActivity

package com.example.administrator.myprogressbar2;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;

import com.example.administrator.myprogressbar2.widget.MyProgressBar;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mBtnStartDown;
    private MyProgressBar myProgressBar;
    private int progress;
    private static final int UPDATA_PROGRESS=0x44;
    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case UPDATA_PROGRESS:
                    if(progress<100){
                        progress++;
                    }
                    myProgressBar.setCurrentProgress(progress);
                    handler.sendEmptyMessageDelayed(UPDATA_PROGRESS,300);
                    break;
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtnStartDown= (Button) findViewById(R.id.btn_startdown);
        mBtnStartDown.setOnClickListener(this);
        myProgressBar= (MyProgressBar) findViewById(R.id.progressbar2);

    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_startdown:
                handler.sendEmptyMessage(UPDATA_PROGRESS);
                break;
        }
    }
}

Progressbar(3)

這裡寫圖片描述

自定義View

package com.example.administrator.myprogressbararc.widget;

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

/**
 * Created by Administrator on 2015/9/16.
 */
public class ProgressbarArc extends View {
    private int width;
    private int height;
    private float a=1.1111f;
    private int maxProgress=100;
    private float currentProgress;
    private Paint mPaintrectangleMax;
    private Paint mPaintrectangleCurrent;
    private Paint mPaintText;
    public int getMaxProgress() {
        return maxProgress;
    }

    public void setMaxProgress(int maxProgress) {
        this.maxProgress = maxProgress;
    }

    public double getCurrentProgress() {
        return currentProgress;
    }

    public void setCurrentProgress(float currentProgress) {
        this.currentProgress = currentProgress;
        invalidate();
    }

    public ProgressbarArc(Context context) {
        super(context);

    }

    public ProgressbarArc(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaintrectangleMax=new Paint();
        mPaintrectangleMax.setColor(Color.BLUE);
        mPaintrectangleMax.setAntiAlias(true);
        mPaintrectangleMax.setTextAlign(Paint.Align.CENTER);
        mPaintrectangleCurrent=new Paint();
        mPaintrectangleCurrent.setColor(Color.GREEN);
        mPaintrectangleCurrent.setStrokeWidth(20);
        mPaintrectangleCurrent.setStyle(Paint.Style.STROKE);
        mPaintrectangleCurrent.setAntiAlias(true);
        mPaintText=new Paint();
        mPaintText.setColor(Color.BLACK);
        mPaintText.setTextSize(50);
        mPaintText.setTextAlign(Paint.Align.CENTER);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width,height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        RectF rectF=new RectF(90,90,300,300);
        RectF rectF1=new RectF(100,100,290,290);
        canvas.drawArc(rectF,0,360,false,mPaintrectangleMax);
        canvas.drawArc(rectF1,0,currentProgress*360f/maxProgress,false,mPaintrectangleCurrent);
        canvas.drawText((float)Math.round(currentProgress*10000/maxProgress)/100+"%",195,195,mPaintText);

    }
}

佈局檔案程式碼就不上了,MainActivity中

package com.example.administrator.myprogressbararc;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;



import com.example.administrator.myprogressbararc.widget.ProgressbarArc;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button mBtnStartDown;
    private ProgressbarArc myProgressBar;
    private float progress;
    private static final int UPDATA_PROGRESS=0x44;
    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case UPDATA_PROGRESS:
                    if(progress<100){
                        progress+=0.25;
                    }
                    myProgressBar.setCurrentProgress(progress);
                    handler.sendEmptyMessageDelayed(UPDATA_PROGRESS,100);
                    break;
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtnStartDown= (Button) findViewById(R.id.btn_progressbar_arc);
        mBtnStartDown.setOnClickListener(this);
        myProgressBar= (ProgressbarArc) findViewById(R.id.progressbararc);

    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_progressbar_arc:
                handler.sendEmptyMessage(UPDATA_PROGRESS);
                break;
        }
    }
}