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)方法用於畫矩形
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型別,即圓弧
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;
}
}
}