說到畫圖,在Android中有兩個很是重要的東西,Paint
和Canvas
。Paint
就是畫筆,Canvas
就是畫布。android
那怎麼繪製一個自定義View呢?我就明人不說暗話了,看代碼吧~canvas
package com.example.chengyingying.androiddemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
public class DemoView extends View {
private Paint myPaint;
public DemoView(Context context) {
this(context,null);
}
public DemoView(Context context, @Nullable AttributeSet attrs) {
this(context,attrs,0);
}
public DemoView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
myPaint = new Paint();
myPaint.setColor(Color.RED);//設置畫筆顏色
myPaint.setStyle(Paint.Style.STROKE);//設置畫筆填充樣式
myPaint.setStrokeWidth(50);//設置畫筆寬度
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(100,100,100,myPaint);
}
}
複製代碼
代碼很簡單,首先建立一個類,而後讓這個類去繼承View
。就表示當前這個類是一個自定義View。若是咱們想寫個像LinearLayout,RelativeLayout這樣的容器,那咱們應該繼承ViewGroup,若是咱們想要在系統自帶控件的基礎上再本身定義或者添加點兒東西的話,那就繼承系統原有的控件便可。好比我想弄的圓形的ImageView,那咱們就繼承ImageView。若是我想作一個花型的按鈕,那我就繼承Button就行。其次咱們就是重寫onDraw(canvas)
,在這個函數裏面有個參數,canvas
,這個就是當前的畫布,咱們要畫東西就在這上面畫。在這裏我給畫筆設置了幾個屬性:bash
myPaint = new Paint();
myPaint.setColor(Color.RED);//設置畫筆顏色
myPaint.setStyle(Paint.Style.STROKE);//設置畫筆填充樣式
myPaint.setStrokeWidth(50);//設置畫筆寬度
複製代碼
而後調用了canvas.drawCircle(100,100,100,myPaint);
畫了一個圓。 而後咱們直接在佈局文件裏以全名的方式引入他便可,例如:ide
<com.example.chengyingying.androiddemo.DemoView
android:layout_width="match_parent"
android:layout_height="match_parent" />
複製代碼
記住,必須是全名。固然咱們也能夠經過代碼使用。直接建立自定義控件的實例便可。記住,若是要在xml
中使用自定義控件,這個構造方法必定要添加。函數
public DemoView(Context context, @Nullable AttributeSet attrs) {
this(context,attrs,0);
}
複製代碼
而後咱們看下效果:工具
要想建立一個自定義控件,就三步便可:佈局
如今看下咱們剛纔用到的畫筆的幾個屬性學習
setColor()this
該函數用於設置畫筆顏色,不說那些顏色相關的東西了,就說下,能夠有那幾只方式設置顏色,簡單粗暴。spa
setStrokeWidth()
用於設置描邊寬度值,單位是px。僅當畫筆的Style樣式是Style.FILL_AND_STROKE
時有效。
cavans就是塊布,你想幹啥,就拿畫筆在這上面畫。如今看下他咋用?
畫布背景設置
有三種方法能夠實現畫布背景設置:
void drawLine(float startX,float startY,float stopX,float stopY,Paint paint) startX:
起始點X座標
startY:
起始點Y座標
stopX:
終點X座標
stopY:
終點Y座標
注:
直線的粗細於Paint.setStrokeWidth有直接關係。因此,paint.setStrokeWidth在Style起做用是,用於設置描邊寬度;在Style不起做用時,用於設置畫筆寬度。
畫點
void drawPonit(float x,float y,Paint paint)
floatx:
點的X座標
floaty:
點的Y座標
點的大小隻與paint.setStrokeWidth(width)有關,而與paint.setStyle無關。
矩形工具類RectF Rect概述
這兩個類都是矩形工具類,根據4個點構造出一個矩形結構。RectF與Rect中的方法,成員變量徹底同樣,惟一不一樣的是:RectF是用來保存float類型數值的矩形結構的,而Rect是用來保存int類型數值的矩形結構的。
構造函數有下面四個:
RectF()
,
RectF(float left,float top,float right,float bottom)
,
RectF(RectF r)
RectF(Rect r)
構造函數以下:
Rect()
Rect(int left,int top,int right,int bottom)
Rect(Rect r)
矩形
void drawRect(float left,float top,float right,float bottom,Paint paint)
void drawRect(RectF recf ,Paint paint)
void drawRect(Rect r,Paint paint)
參數:
第一個的寫法是直接傳入左
,上
,右
,下
四個點,畫出矩形
第二,第三個構造函數是根據傳入RectF或者Rect矩形變量來指定所畫的矩形。
Canvans變換
canvas中有一個函數translate()用來實現畫布平移的,畫布的原狀是以左上角爲原點,向左是X軸正方向,向下是Y軸正方向。
translate函數其實實現的想當於平移座標系,即平移座標系的圓點位置。translate()函數的原型以下:
void translate(float dx,float dy)
參數說明:
float dx:
水平方向平移的距離,正數指向正方向(向右)平移的量,負數爲向(向左)平移的量
float dy:
垂直方向平移的距離,正數指向正方向(向下)平移的量,負數爲向負方向(向上)平移的量
畫布的旋轉是默認圍繞座標原點來旋轉的,這裏容易產生錯覺,看起來以爲是圖片旋轉了,其實咱們旋轉的是畫布,之後在此畫布上畫的東西顯示出來的時候所有看起來都是旋轉的。Rotate函數有兩個構造函數:
void rotate(float degress)
void rotate(float degress,float px,float py)
第一個構造函數直接輸入旋轉的度數,正數是順時針旋轉,負數指逆時針旋轉,它的旋轉中心點是原點(0,0)
第二個構造函數除了度數之外,還能夠指定旋轉的中心點座標(px,py)
public void scale(float sx,float sy)
參數:
float sx:
水平方向伸縮的比例,sx爲小數爲縮小,sx爲整數爲放大 float sy:
垂直方向伸縮比例,sy爲小數爲縮小,整數爲放大。
屏幕顯示與Canvas的關係
畫布裁剪
裁剪畫布是利用Clip系列函數,經過與Rect、Path、Region取交、並、差等集合運算來得到最新的畫布形狀。除了調用Save、Restore函數之外,這個操做是不可逆的,一但Canvas畫布被裁剪,就不能再被恢復!
boolean clipPath(Path path)
boolean clipPath(Path path, Region.Op op)
boolean clipRect(Rect rect, Region.Op op)
boolean clipRect(RectF rect, Region.Op op)
boolean clipRect(int left, int top, int right, int bottom)
boolean clipRect(float left, float top, float right, float bottom)
boolean clipRect(RectF rect)
boolean clipRect(float left, float top, float right, float bottom, Region.Op op)
boolean clipRect(Rect rect)
boolean clipRegion(Region region)
boolean clipRegion(Region region, Region.Op op)
畫布的保存於恢復
Save():
每次調用Save()函數,都會把當前的畫布的狀態進行保存,而後放入特定的棧中;
restore():
每當調用Restore()函數,就會把棧中最頂層的畫布狀態取出來,並按照這個狀態恢復當前的畫布,並在這個畫布上作畫。
先聲明:這篇文章是本身買了本啓艦大神的書,而後邊看出,邊看他博客,摘下來一些東西。本身寫這個東西,一是加深本身的理解,二是爲了方便本身在坐地鐵的時候,學習看,方便。
出處:https://blog.csdn.net/harvic880925/article/details/39080931
最後強烈建議你們買一本啓艦大神的《Android自定義控件入門與實戰》這本書,寫的很好,通俗易懂。
複製代碼