什么是自定義控件
自定義控件有三個點论熙,布局繪制和觸摸反饋福青。接下來的章節(jié)我們先說繪制,繪制就是在控件上顯示需要我們用代碼控制繪制細節(jié)脓诡,顯示系統(tǒng)自帶控件顯示不出的內(nèi)容无午,不管是多復(fù)雜的顯示我們能夠通過自定義控件繪制出來。
android的繪制跟我們平常的畫畫一樣祝谚,我們在畫畫的時候需要筆和紙宪迟。android開發(fā)中筆就是Paint類,Canvas就是紙交惯。凡是一些設(shè)置畫筆的粗細次泽、畫筆顏色穿仪、透明度都是在Paint類中設(shè)置的,凡是能畫出某種物體比如繪制圓形意荤、矩形啊片、文字都是在canvas里進行完成。
自定義繪制非常容易只需要重寫onDraw方法玖像,將創(chuàng)建好Paint對象傳入canvas中,這里需要注意的是onDraw方法需要super.onDraw方法紫谷,而且android中的坐標系是左上角為(0,0)原點御铃。
private Paint paint = new Paint();
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(10, 10, 100, 100, paint);
}
Paint相關(guān)方法
1.setColor
public void setColor(@ColorInt int color)
設(shè)置畫筆的顏色碴里,向下邊這樣沈矿。
paint.setColor(Color.YELLOW);
canvas.drawRect(10, 10, 100, 100, paint);
2.setAntiAlias
public void setAntiAlias(boolean aa)
一些不規(guī)則的圖形例如文字上真,圓形需要打開抗鋸齒功能讓邊緣更平滑。我們可以通過setAntiAlias方法可以設(shè)置是否使用抗鋸齒羹膳,也可以在Paint構(gòu)造函數(shù)中傳入ANTI_ALIAS_FLAG
睡互。
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setAntiAlias(true);
下邊繪制一個圓形放大一下可以看到效果
抗鋸齒依賴算法實現(xiàn)的,通過修改邊緣處的顏色陵像,讓圖形有了平滑的感覺就珠。
3.setStyle
public void setStyle(Style style)
setStyle方法設(shè)置填充樣式,對文字以及圖形都有效醒颖。樣式一共有三種妻怎,Paint.Style.FILL填充模式,Paint.Style.STROKE描邊模式泞歉,以及Paint.Style.FILL_AND_STROKE兩個模式一起使用逼侦,默認情況下是FILL填充模式。
4.setStrokeWidth
設(shè)置描邊的寬度腰耙,在畫筆在STROKE和FILL_AND_STROKE時使用榛丢。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(20);
canvas.drawCircle(200, 200, 50, paint);
Canvas基礎(chǔ)
1.畫布顏色設(shè)置
canvas可以實現(xiàn)畫布的顏色設(shè)置,通過以下方法實現(xiàn)挺庞。
public void drawColor(@ColorInt int color)
public void drawARGB(int a, int r, int g, int b)
public void drawRGB(int r, int g, int b)
根據(jù)drawColor方法可以知道晰赞,我們需要傳入8位的顏色值,drawARGB傳入A选侨、R掖鱼、G、B的顏色取值0~255范圍援制。drawRGB函數(shù)只傳入R戏挡、G、B隘谣,Alpha默認是255增拥。
canvas.drawColor(Color.parseColor("#FF0000"));
canvas.drawRGB(255,0,0);
canvas.drawARGB(255,255,0,0);
2.繪制點
public void drawPoint(float x, float y, @NonNull Paint paint)
drawPoint方法x啄巧,y分別是設(shè)置點的坐標,點的大小可以用setStrokeWidth方法設(shè)置大小掌栅。
paint.setStrokeWidth(80);
canvas.drawPoint(120, 120, paint);
多點繪制可以通過drawPoints方法來實現(xiàn)秩仆。
public void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
@NonNull Paint paint)
public void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint)
這里pts是設(shè)置點的坐標,設(shè)置為{x1,y1,x2,y2...}猾封,offset是跳過數(shù)值的個數(shù)(一個點有兩個數(shù))澄耍。count代表繪制數(shù)字的個數(shù)。
paint.setColor(Color.RED);
paint.setStrokeWidth(80);
float[] pts = {50, 50, 100, 100, 200, 200, 300, 300};
canvas.drawPoints(pts, 2/* 跳過兩個數(shù)晌缘,即前兩個 0 */, 6/* 一共繪制 6 個數(shù)(3 個點) */, paint);
3.繪制直線
public void drawLine(float startX, float startY, float stopX, float stopY,
@NonNull Paint paint)
startX齐莲、startY、stopX磷箕、stopY分別代表坐標的起始位置以及終止位置选酗。
繪制多條直線
public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
@NonNull Paint paint)
public void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint)
與多點繪制相似,可以利用drawLines方法繪制多條線段岳枷。
4.繪制矩形
public void drawRect(@NonNull RectF rect, @NonNull Paint paint)
public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)
利用drawRect方法可以繪制矩形我們可以通過矩形的四個點傳值也可以通過RectF芒填、Rect傳值。
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(100, 100, 200, 200, paint);
5.繪制圓角矩形
public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint)
利用drawRoundRect方法可以繪制出帶有圓角的矩形參數(shù)RectF設(shè)置繪制的矩形空繁,rx殿衰、ry分別代表x軸和y軸的半徑。
6.繪制圓形
public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
cx和cy分別設(shè)置圓心點的坐標盛泡,radius設(shè)置圓形半徑闷祥。
canvas.drawCircle(100, 100, 30, paint);
7.繪制橢圓
public void drawOval(@NonNull RectF oval, @NonNull Paint paint)
drawOval是繪制橢圓的方法,根據(jù)矩形oval區(qū)域繪制出橢圓傲诵。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
paint2.setStyle(Paint.Style.STROKE);
paint2.setColor(Color.RED);
paint2.setStrokeWidth(5);
RectF rect = new RectF(100, 100, 400, 300);
canvas.drawOval(rect, paint);
canvas.drawRect(rect, paint2);
另外繪制橢圓還有其他重載方法凯砍,drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)根據(jù)邊界點繪制橢圓。
8.繪制弧形
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
@NonNull Paint paint)
弧是橢圓的一部分掰吕,橢圓又是根據(jù)矩形生成的果覆,所以弧形也是根據(jù)矩形而來。
這里oval是矩形區(qū)域殖熟,startAngle是弧形的起始弧度局待,sweepAngle是弧形劃過的角度;useCenter 表示是否連接到圓心菱属,如果不連接到圓心钳榨,就是弧形,如果連接到圓心纽门,就是扇形薛耻。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
paint2.setStyle(Paint.Style.STROKE);
paint2.setColor(Color.RED);
paint2.setStrokeWidth(5);
RectF rect = new RectF(100, 100, 400, 300);
canvas.drawArc(rect, 0, 90, true, paint);
canvas.drawArc(rect, 90, 180, false, paint2);
Path路徑
在android開發(fā)中通過canvas繪制路徑
void drawPath(Path path, Paint paint)
接下來看看path下有哪些方法。
1.直線路徑
畫直線一般需要三個函數(shù)
public void moveTo(float x, float y)
x,y設(shè)置起始點的位置赏陵。由當(dāng)前位置 (0, 0) 移動致 (x, y)
public void lineTo(float x, float y)
lineTo方法是根據(jù)起始點設(shè)置終點饼齿。
public void close()
如果前邊的劃線沒有形成閉環(huán)那么調(diào)用close方法可以首尾連接起來饲漾。當(dāng)需要填充圖形時(即 Paint.Style 為 FILL 或 FILL_AND_STROKE),Path 會自動封閉子圖形缕溉。后邊會有介紹考传。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
Path path = new Path();
path.moveTo(150, 150);//移動到(150,150)初始化為原點
path.lineTo(50, 250);//第一條線
path.lineTo(250, 250);//第二條線
path.close();
canvas.drawPath(path, paint);
close方法調(diào)用后形成一個閉環(huán)形成一個三角形证鸥。
2.弧線路徑
public void arcTo(@NonNull RectF oval, float startAngle, float sweepAngle,
boolean forceMoveTo)
這個方法和 Canvas.drawArc() 比起來僚楞,少了一個參數(shù) useCenter,而多了一個參數(shù) forceMoveTo枉层,forceMoveTo是否連線到弧形起點泉褐。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
RectF rect = new RectF(200, 200, 300, 300);
Path path = new Path();
path.moveTo(100, 100);
path.lineTo(150, 150);
path.arcTo(rect, -90, 90, true);
canvas.drawPath(path, paint);
path.arcTo(rect, -90, 90, false);
3.addXXX系列方法
添加圓形
public void addCircle(float x, float y, float radius, @NonNull Direction dir)
Direction是指路徑方向CW順時針,CCW逆時針鸟蜡。無論是順時針逆時針膜赃,僅僅是方向不同,這里后邊會介紹矩欠,其他addxxx方法也類似财剖。
添加橢圓
public void addOval(@NonNull RectF oval, @NonNull Direction dir)
添加矩形
public void addRect(@NonNull RectF rect, @NonNull Direction dir)
添加圓角矩形
public void addRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Direction dir)
4.填充方式
public void setFillType(@NonNull FillType ft)
- WINDING (默認值)顯示方向相交的內(nèi)容
- EVEN_ODD 相交的地方填充
- INVERSE_WINDING
- INVERSE_EVEN_ODD
path.setFillType(Path.FillType.WINDING);
path.addCircle(200, 200, 100, Path.Direction.CW);
path.addCircle(290, 200, 100, Path.Direction.CW);
canvas.drawPath(path, paint);
path.setFillType(Path.FillType.WINDING);
path.addCircle(200, 200, 100, Path.Direction.CW);
path.addCircle(290, 200, 100, Path.Direction.CCW);
canvas.drawPath(path, paint);
WINDING方式如果兩個圖形的path方向相同悠夯,即方向不想交癌淮,則可以全部顯示,若方向不同沦补,就產(chǎn)生了相交區(qū)域乳蓄。
EVEN_ODD與WINDING不同同方向效果一致。
INVERSE_WINDING與INVERSE_EVEN_ODD與剛剛介紹的兩個相反夕膀。
5.重置路徑
當(dāng)我們需要繪制一條全新的路徑的時候虚倒,可以重置路徑的對象,這樣我們就可以不需要重新定義路徑的對象了产舞。
void reset()
void rewind()
reset會保留當(dāng)前的數(shù)據(jù)結(jié)構(gòu)魂奥,會清除FillType,rewind會清除數(shù)據(jù)空間,但不會清除FillType易猫。