成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

View之Canvas,Paint,Matrix,RectF等介紹

khs1994 / 2054人閱讀

摘要:將當(dāng)前狀態(tài)保存在堆棧,之后可以調(diào)用的平移旋轉(zhuǎn)錯切剪裁等操作?;謴?fù)為之前堆棧保存的狀態(tài),防止后對執(zhí)行的操作對后續(xù)的繪制有影響。

目錄介紹

1.Paint畫筆介紹

1.1 圖形繪制

1.2 文本繪制

2.Canvas畫布介紹

2.1 設(shè)置屬性

2.2 畫圖【重點】

2.3 Canvas對象的獲取方式

2.4 Canvas的作用

2.5 Canvas繪制圓和橢圓

2.6 Canvas繪制矩形、圓角矩形

2.7 Canvas繪制文字

2.8 Canvas繪制弧形、封閉弧形

2.9 Canvas繪制Path路徑

3.Matrix變換矩陣介紹

3.1 translate平移

3.2 rorate旋轉(zhuǎn)

3.3 scale縮放

3.4 skew扭曲

4.RectF介紹

4.1 Rect簡單屬性

4.2 Rect父類的實現(xiàn)

4.3 Rect常用的一些方法

5.關(guān)于使用到這幾個屬性的自定義View

5.0 知道了這幾個,需要練手寫下案例

5.1 自定義輪播圖圓點

5.2 自定義圓環(huán)百分比進度條

好消息

博客筆記大匯總【16年3月到至今】,包括Java基礎(chǔ)及深入知識點,Android技術(shù)博客,Python學(xué)習(xí)筆記等等,還包括平時開發(fā)中遇到的bug匯總,當(dāng)然也在工作之余收集了大量的面試題,長期更新維護并且修正,持續(xù)完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計47篇[近20萬字],轉(zhuǎn)載請注明出處,謝謝!

鏈接地址:https://github.com/yangchong2...

如果覺得好,可以star一下,謝謝!當(dāng)然也歡迎提出建議,萬事起于忽微,量變引起質(zhì)變!

1.Paint畫筆介紹

Paint即畫筆,在繪圖過程中起到了極其重要的作用,畫筆主要保存了顏色, 樣式等繪制信息,指定了如何繪制文本和圖形,畫筆對象有很多設(shè)置方法,大體上可以分為兩類,一類與圖形繪制相關(guān),一類與文本繪制相關(guān)。

1.1 圖形繪制

常用的方法有這些

設(shè)置繪制的顏色,a代表透明度,r,g,b代表顏色值。 
* setAlpha(int a); 
設(shè)置繪制圖形的透明度。
* setColor(int color); 
設(shè)置繪制的顏色,使用顏色值來表示,該顏色值包括透明度和RGB顏色。 
* setAntiAlias(boolean aa);
設(shè)置是否使用抗鋸齒功能,會消耗較大資源,繪制圖形速度會變慢。 
* setDither(boolean dither); 
設(shè)定是否使用圖像抖動處理,會使繪制出來的圖片顏色更加平滑和飽滿,圖像更加清晰 
* setFilterBitmap(boolean filter); 
如果該項設(shè)置為true,則圖像在動畫進行中會濾掉對Bitmap圖像的優(yōu)化操作,加快顯示速度,本設(shè)置項依賴于dither和xfermode的設(shè)置 
* setMaskFilter(MaskFilter maskfilter); 
設(shè)置MaskFilter,可以用不同的MaskFilter實現(xiàn)濾鏡的效果,如濾化,立體等 
* setColorFilter(ColorFilter colorfilter); 
設(shè)置顏色過濾器,可以在繪制顏色時實現(xiàn)不用顏色的變換效果 
* setPathEffect(PathEffect effect); 
設(shè)置繪制路徑的效果,如點畫線等 
* setShader(Shader shader); 
設(shè)置圖像效果,使用Shader可以繪制出各種漸變效果 
* setShadowLayer(float radius ,float dx,float dy,int color); 
在圖形下面設(shè)置陰影層,產(chǎn)生陰影效果,radius為陰影的角度,dx和dy為陰影在x軸和y軸上的距離,color為陰影的顏色 
* setStyle(Paint.Style style); 
設(shè)置畫筆的樣式,為FILL,F(xiàn)ILL_AND_STROKE,或STROKE 
* setStrokeCap(Paint.Cap cap); 
當(dāng)畫筆樣式為STROKE或FILL_AND_STROKE時,設(shè)置筆刷的圖形樣式,如圓形樣式  Cap.ROUND,或方形樣式Cap.SQUARE 
* setSrokeJoin(Paint.Join join); 
設(shè)置繪制時各圖形的結(jié)合方式,如平滑效果等 
* setStrokeWidth(float width); 
當(dāng)畫筆樣式為STROKE或FILL_AND_STROKE時,設(shè)置筆刷的粗細(xì)度 
* setXfermode(Xfermode xfermode); 
設(shè)置圖形重疊時的處理方式,如合并,取交集或并集,經(jīng)常用來制作橡皮的擦除效果 
```

1.2 文本繪制

常用的方法有這些

模擬實現(xiàn)粗體文字,設(shè)置在小字體上效果會非常差 
* setSubpixelText(boolean subpixelText); 
設(shè)置該項為true,將有助于文本在LCD屏幕上的顯示效果 
* setTextAlign(Paint.Align align); 
設(shè)置繪制文字的對齊方向 
* setTextScaleX(float scaleX); 
設(shè)置繪制文字x軸的縮放比例,可以實現(xiàn)文字的拉伸的效果 
* setTextSize(float textSize); 
設(shè)置繪制文字的字號大小 
* setTextSkewX(float skewX); 
設(shè)置斜體文字,skewX為傾斜弧度 
* setTypeface(Typeface typeface); 
設(shè)置Typeface對象,即字體風(fēng)格,包括粗體,斜體以及襯線體,非襯線體等 
* setUnderlineText(boolean underlineText); 
設(shè)置帶有下劃線的文字效果 
* setStrikeThruText(boolean strikeThruText); 
設(shè)置帶有刪除線的效果 
```


2.Canvas畫布介紹

當(dāng)我們調(diào)整好畫筆之后,現(xiàn)在需要繪制到畫布上,這就得用Canvas類了。在android中既然把Canvas當(dāng)做畫布,那么就可以在畫布上繪制我們想要的任何東西。除了在畫布上繪制之外,還需要設(shè)置一些關(guān)于畫布的屬性,比如,畫布的顏色、尺寸等。

2.1 設(shè)置屬性

一般屬性有:

* Canvas(Bitmap bitmap): 以bitmap對象創(chuàng)建一個畫布,則將內(nèi)容都繪制在bitmap上,因此bitmap不得為null。
* Canvas(GL gl): 在繪制3D效果時使用,與OpenGL相關(guān)。
* isOpaque(boolean isOpaque):檢測是否支持透明。
* setViewport(int left, int top, int right, int bottom, int clipflag):  設(shè)置畫布中顯示窗口。
* drawColor(int color): 設(shè)置Canvas的背景顏色。
* setBitmap(Bitmap mBitmap):  設(shè)置具體畫布,畫的內(nèi)容,保存為一個Bitmap。
* clipRect(float left, float top, float right, float bottom): 設(shè)置顯示區(qū)域,即設(shè)置裁剪區(qū)。
* translate(float x, float  y): 平移畫布。
* rotate(float degree, float px, float py):  旋轉(zhuǎn)畫布 。
* skew(float sx, float sy):  設(shè)置偏移量。 
* save(): 將Canvas當(dāng)前狀態(tài)保存在堆棧,save之后可以調(diào)用Canvas的平移、旋轉(zhuǎn)、錯切、剪裁等操作。
* restore(): 恢復(fù)為之前堆棧保存的Canvas狀態(tài),防止save后對Canvas執(zhí)行的操作對后續(xù)的繪制有影響。restore和save要配對使用,restore可以比save少,但不能比save多,否則會引發(fā)error。save和restore之間,往往夾雜的是對Canvas的特殊操作。
* save(int num):將Canvas當(dāng)前狀態(tài)保存在堆棧,并予以編號int
* restoreToCount(int num):恢復(fù)為之前堆棧保存的編號為int的Canvas狀態(tài)
* concat(Matrix matrix):畫布關(guān)聯(lián)矩陣,畫出來的內(nèi)容按矩陣改變,而不是畫布改變。

注:這種方式畫Drawable怎么設(shè)置透明度呢?((BitmapDrawable)Drawable).getPaint().setAlpha(mBgAlpha);
```

2.2 畫圖【重點】

畫圖部分

將畫筆設(shè)置的顏色和透明度鋪滿畫布
* drawRect(RectF rect, Paint paint) 
繪制矩形,參數(shù)一為RectF一個區(qū)域 
* drawRect(float left, float top, float right, float bottom, Paint paint)
繪制矩形,left:矩形left的x坐標(biāo),top:矩形top的y坐標(biāo),right:矩形right的x坐標(biāo),bottom:矩形bottom的y坐標(biāo)
* drawRoundRect(RectF rect, float rx, float ry, Paint paint)
繪制圓角矩形, rx:x方向的圓角半徑,ry:y方向的圓角半徑
* drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)        
* drawPath(Path path, Paint paint) 
繪制一個路徑,參數(shù)一為Path路徑對象
* drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)  
貼圖,參數(shù)一就是我們常規(guī)的Bitmap對象,參數(shù)二是源區(qū)域(這里是bitmap),參數(shù)三是目標(biāo)區(qū)域(應(yīng)該在canvas的位置和大小),參數(shù)四是Paint畫刷對象,因為用到了縮放和拉伸的可能,當(dāng)原始Rect不等于目標(biāo)Rect時性能將會有大幅損失。
* drawBitmap (Bitmap bitmap, float left, float top, Paint paint)
* drawLine(float startX, float startY, float stopX, float stopY, Paintpaint)
畫線,參數(shù)一起始點的x軸位置,參數(shù)二起始點的y軸位置,參數(shù)三終點的x軸水平位置,參數(shù)四y軸垂直位置,最后一個參數(shù)為Paint 畫刷對象。 
* drawPoint(float x, float y, Paint paint) 
畫點,參數(shù)一水平x軸,參數(shù)二垂直y軸,第三個參數(shù)為Paint對象。
* drawText(String text, float x, floaty, Paint paint)  
渲染文本,Canvas類除了上面的還可以描繪文字,參數(shù)一是String類型的文本,參數(shù)二文字左側(cè)到x軸距離,參數(shù)三文字BaseLine到y(tǒng)軸距離,參數(shù)四是Paint對象。
* drawOval(RectF oval, Paint paint)
繪制橢圓,參數(shù)一是掃描區(qū)域,參數(shù)二為paint對象
* drawOval(float left, float top, float right, float bottom, Paint paint)
* drawCircle(float cx, float cy, float radius,Paint paint)
繪制圓,參數(shù)一是中心點的x軸,參數(shù)二是中心點的y軸,參數(shù)三是半徑,參數(shù)四是paint對象;
* drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
畫弧,參數(shù)一是RectF對象,指定圓弧的外輪廓矩形區(qū)域,參數(shù)二是起始角(度)在電弧的開始,參數(shù)三掃描角(度)開始順時針測量的,參數(shù)四是如果這是真的話,包括橢圓中心的電弧,并關(guān)閉它,如果它是假這將是一個弧線,參數(shù)五是Paint對象;
```
2.3 Canvas對象的獲取方式

2.3.1 Canvas對象的獲取方式有兩種:

第一種通過重寫View.onDraw方法,View中的Canvas對象會被當(dāng)做參數(shù)傳遞過來,操作這個Canvas,效果會直接反應(yīng)在View中。

第二種通過new創(chuàng)建一個Canvas對象

代碼如下所示

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

Canvas canvas = new Canvas();

2.4 Canvas的作用

Canvas可以繪制的對象有:弧線(arcs)、填充顏色(argb和color)、Bitmap、圓(circle和oval)、點(point)、線(line)、矩形(Rect)、圖片(Picture)、圓角矩形(RoundRect)、文本(text)、頂點(Vertices)、路徑(path)。

2.5 Canvas繪制圓和橢圓

繪制圓

private Paint paint = new Paint();

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    paint.setAntiAlias(true);
    paint.setColor(Color.BLUE);
    paint.setStyle(Paint.Style.FILL);
    canvas.drawCircle(200,200,100 , paint);
}

2.6 Canvas繪制矩形、圓角矩形

如下所示

private Paint paint = new Paint();

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    paint.setAntiAlias(true);
    paint.setColor(Color.RED);
    paint.setStyle(Paint.Style.FILL);
    canvas.drawRect(100, 100, 200, 200, paint);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        canvas.drawRoundRect(400, 100, 600, 300, 30, 30, paint);
    }
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(20);
    canvas.drawRect(100, 400, 300, 600, paint);
}

2.7 Canvas繪制文字

Canvas繪制文字

private Paint paint = new Paint();

@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    paint.setAntiAlias(true);
    paint.setColor(Color.RED);
    paint.setTextSize(100);
    canvas.drawText("瀟湘劍雨", 100, 100, paint);
}

2.8 Canvas繪制弧形、封閉弧形

繪制弧形、封閉弧形

private Paint paint = new Paint();

@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    paint.setAntiAlias(true);
    paint.setColor(Color.RED);
    RectF rel = new RectF(50, 50, 150, 150);
    //實心圓弧
    canvas.drawArc(rel, 0, 135, false, paint);
    //實心圓弧 將圓心包含在內(nèi)
    RectF rel2 = new RectF(50, 200, 150, 300);
    canvas.drawArc(rel2, 0, 135, true, paint);
    //設(shè)置空心Style
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(20);
    RectF rel3 = new RectF(50, 350, 150, 450);
    canvas.drawArc(rel3, 0, 270, false, paint);
    RectF rel4 = new RectF(50, 250, 150, 600);
    canvas.drawArc(rel4, 0, 270, true, paint);
}

2.9 Canvas繪制Path路徑

Canvas繪制Path路徑

private Paint paint = new Paint();
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Path angle = new Path();
    angle.moveTo(250, 0);
    angle.lineTo(0, 500);
    angle.lineTo(100, 300);
    angle.lineTo(200, 350);
    angle.lineTo(500, 500);
    angle.close();
    canvas.drawPath(angle, paint);
}

3.Matrix變換矩陣介紹【Canvas位置轉(zhuǎn)換】

思考:如果要畫一個儀表盤(數(shù)字圍繞顯示在一個圓圈中),或者類似鐘表指針樣的控件,如何實現(xiàn)?

Android還提供了一些對Canvas位置轉(zhuǎn)換的方法:rorate、scale、translate、skew(扭曲)等,而且它允許你通過獲得它的轉(zhuǎn)換矩陣對象(getMatrix方法)直接操作它。這些操作就像是雖然你的筆還是原來的地方畫,但是畫紙旋轉(zhuǎn)或者移動了,所以你畫的東西的方位就產(chǎn)生變化。為了方便一些轉(zhuǎn)換操作,Canvas還提供了保存和回滾屬性的方法(save和restore),比如你可以先保存目前畫紙的位置(save),然后旋轉(zhuǎn)90度,向下移動100像素后畫一些圖形,畫完后調(diào)用restore方法返回到剛才保存的位置。

3.1 translate平移 3.2 rorate旋轉(zhuǎn)

rorate旋轉(zhuǎn)

private Paint mPaint = new Paint();

@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawColor(Color.BLUE);
    mPaint.setColor(Color.RED);
    canvas.drawRect(new Rect(0, 0, 800, 800), mPaint);
    canvas.save();
    mPaint.setColor(Color.GREEN);
    canvas.rotate(45,400,400);
    canvas.drawRect(new Rect(0, 0, 800, 800), mPaint);
    canvas.restore();
}

源代碼有兩個可以使用的方法:

/**  
 * Preconcat the current matrix with the specified rotation.  

 */  
public native void rotate(float degrees);    
/**  
 * Preconcat the current matrix with the specified rotation.   
 * @param degrees The amount to rotate, in degrees  
 * @param px The x-coord for the pivot point (unchanged by the rotation)  
 * @param py The y-coord for the pivot point (unchanged by the rotation)  
 */  
public final void rotate(float degrees, float px, float py) {  
    translate(px, py);  
    rotate(degrees);  
    translate(-px, -py);  
}  
```


3.3 scale縮放

scale縮放

private Paint mPaint = new Paint();

@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawColor(Color.YELLOW);
    mPaint.setColor(Color.RED);
    canvas.drawRect(new Rect(0, 0, 800, 800), mPaint);
    // 保存畫布狀態(tài)
    canvas.save();
    canvas.scale(0.5f, 0.5f);
    mPaint.setColor(Color.GREEN);
    canvas.drawRect(new Rect(0, 0, 800, 800), mPaint);
    // 畫布狀態(tài)回滾
    canvas.restore();
    canvas.scale(0.5f, 0.5f, 400, 400);
    mPaint.setColor(Color.BLUE);
    canvas.drawRect(new Rect(0, 0, 800, 800), mPaint);
}

源碼如下所示

/**  
 * Preconcat the current matrix with the specified scale.   
 * @param sx The amount to scale in X  

 */  
public native void scale(float sx, float sy);  

/**  
 * Preconcat the current matrix with the specified scale.  
 * @param sx The amount to scale in X  
 * @param sy The amount to scale in Y  
 * @param px The x-coord for the pivot point (unchanged by the scale)  
 * @param py The y-coord for the pivot point (unchanged by the scale)  
 */  
public final void scale(float sx, float sy, float px, float py) {  
    translate(px, py);  
    scale(sx, sy);  
    translate(-px, -py);  
}  
```



3.4 skew扭曲 4.RectF介紹 4.1 Rect簡單屬性

這是一個我們常用的一個“繪畫相關(guān)的工具類”,常用語描述長方形/正方形,他只有4個屬性

public int left;
public int top;
public int right;
public int bottom;

其中常用的構(gòu)造方法如下所示

public Rect(int left, int top, int right, int bottom) {
    this.left = left;
    this.top = top;
    this.right = right;
    this.bottom = bottom;
}

public Rect(Rect r) {
    if (r == null) {
        left = top = right = bottom = 0;
    } else {
        left = r.left;
        top = r.top;
        right = r.right;
        bottom = r.bottom;
    }
}

這4個屬性描述著這一個“方塊”,但是這有一個知識點需要理清楚,先看這張圖

4.2 Rect父類的實現(xiàn)

實現(xiàn)了Parcelable 所以需要實現(xiàn)一堆Object的方法,諸如equals,toString等等,來簡單看一看

對于equals方法,首先先對傳來的對象進行判空,類型判斷,再強轉(zhuǎn)成Rect對象,最后還是一個個去比對那4個屬性。

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Rect r = (Rect) o;
    return left == r.left && top == r.top && right == r.right && bottom == r.bottom;
}

@Override
public int hashCode() {
    int result = left;
    result = 31 * result + top;
    result = 31 * result + right;
    result = 31 * result + bottom;
    return result;
}

@Override
public String toString() {
    StringBuilder sb = new StringBuilder(32);
    sb.append("Rect("); sb.append(left); sb.append(", ");
    sb.append(top); sb.append(" - "); sb.append(right);
    sb.append(", "); sb.append(bottom); sb.append(")");
    return sb.toString();
}

4.3 Rect常用的一些方法

獲取“寬”

//文章開頭說的公式在這里得到了應(yīng)驗
public final int width() {
    return right - left;
}

獲取“高”

public final int height() {
    return bottom - top;
}

有效性的判斷

//因為left是最左側(cè),right比left還小不就不成形了么?寬高同是如此
public final boolean isEmpty() {
    return left >= right || top >= bottom;
}

全部置0操作

public void setEmpty() {
    left = right = top = bottom = 0;
}

設(shè)置參數(shù)方法,和構(gòu)造函數(shù)的區(qū)別僅在于不會創(chuàng)建新對象

public void set(int left, int top, int right, int bottom) {
    this.left = left;
    this.top = top;
    this.right = right;
    this.bottom = bottom;
}

5.關(guān)于使用到這幾個屬性的自定義View

上面比較詳細(xì)介紹了Canvas,Paint,Matrix,RectF等等的屬性,作用,常用方法,接下來就需要結(jié)合具體業(yè)務(wù)需求練手寫一下小案例自定義控件呢

5.1 自定義輪播圖圓點

5.1.1 需求介紹

繪制圓環(huán),一個實心中心圓,還有一個外圓環(huán)

此控件可以設(shè)置寬度和高度,可以設(shè)置顏色

5.1.2 思路介紹

3.2.1 既然是繪制圓形,可以寫一個繼承View的自定義view

3.2.2 重寫onDraw方法,獲取控件寬高,然后比較寬高值,取小值的一半作為圓的半徑

3.2.3 然后分別繪制選中狀態(tài)和未選中狀態(tài)的圓

3.2.4 創(chuàng)建畫筆Paint,并且設(shè)置相關(guān)屬性,比如畫筆顏色,類型等

3.2.5 利用canvas繪制圓,然后再又用相同方法繪制外邊緣

3.2.6 自定義一個是否選中狀態(tài)的方法,傳入布爾值是否選中,然后調(diào)用view中invalidate方法

5.1.3 代碼介紹

具體代碼如下所示:

/**
 * 
 *     @author yangchong
 *     blog  : https://github.com/yangchong211
 *     time  : 2016/5/18
 *     desc  : 紅點自定義控件
 *     revise: 建議設(shè)置紅點寬高一樣,否則是橢圓
 * 
*/ public class DotView extends View { private boolean isInit = false; private boolean isSelected = false; private float mViewHeight; private float mViewWidth; private float mRadius; private Paint mPaintBg = new Paint(); private int mBgUnselectedColor = Color.parseColor("#1A000000"); private int mBgSelectedColor = Color.parseColor("#FDE26E"); private static final float mArcWidth = 2.0f; public DotView(Context context) { super(context); } public DotView(Context context, AttributeSet attrs) { super(context, attrs); } public DotView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (!isInit) { isInit = true; mViewHeight = getHeight(); mViewWidth = getWidth(); if (mViewHeight >= mViewWidth) { mRadius = mViewWidth / 2.f; } else { mRadius = mViewHeight / 2.f; } } //是否選中 if (isSelected){ drawSelectedDot(canvas); } else{ drawUnSelectedDot(canvas); } } /** * 繪制選中指示器紅點 * @param canvas canvas */ private void drawSelectedDot(Canvas canvas) { //設(shè)置paint相關(guān)屬性 mPaintBg.setAntiAlias(true); mPaintBg.setColor(mBgSelectedColor); mPaintBg.setStyle(Style.FILL); //繪制圓 canvas.drawCircle(mViewWidth / 2.f, mViewHeight / 2.f, mRadius - 8.f, mPaintBg); mPaintBg.setStyle(Style.STROKE); float offset = 1.f + mArcWidth; RectF oval = new RectF(mViewWidth / 2.f - mRadius + offset, mViewHeight / 2.f - mRadius + offset, mViewWidth / 2.f + mRadius - offset, mViewHeight / 2.f + mRadius - offset); //繪制指定的弧線,該弧線將被縮放以適應(yīng)指定的橢圓形。 canvas.drawArc(oval, 0.f, 360.f, false, mPaintBg); } /** * 繪制未選中指示器紅點 * @param canvas canvas */ private void drawUnSelectedDot(Canvas canvas) { mPaintBg.setAntiAlias(true); mPaintBg.setColor(mBgUnselectedColor); mPaintBg.setStyle(Style.FILL); canvas.drawCircle(mViewWidth / 2.f, mViewHeight / 2.f, mRadius - 8.f, mPaintBg); } /** * 設(shè)置是否選中 * @param isSelected isSelected */ public void setIsSelected(boolean isSelected) { this.isSelected = isSelected; //使整個視圖無效。如果視圖是可見的,則{@link#onDraw(android.Graphics.Canvas)}將在將來的某個時候被調(diào)用。 //調(diào)用該方法,會進行重新繪制,也就是調(diào)用onDraw方法 this.invalidate(); } }

5.2 自定義圓環(huán)百分比進度條

5.2.1 需求分析

1.業(yè)務(wù)需求:可以設(shè)置圓角,可以設(shè)置圓形,如果是圓角則必須設(shè)置半徑,默認(rèn)圓角半徑為10dp

2.如果設(shè)置了圓形,則即使設(shè)置圓角也無效;如果設(shè)置非圓形,則圓角生效,同時需要判斷圓角半徑是否大于控件寬高,處理邊界邏輯

3.當(dāng)設(shè)置圓形的時候,即使設(shè)置寬高不一樣,那么取寬高中的最小值的一半為圓形半徑

5.2.2 代碼介紹

代碼如下所示

public class ARoundImageView extends AppCompatImageView {

    /*
     *   Paint:畫筆
     *   Canvas:畫布
     *   Matrix:變換矩陣
     *
     *   業(yè)務(wù)需求:可以設(shè)置圓角,可以設(shè)置圓形,如果是圓角則必須設(shè)置半徑,默認(rèn)圓角半徑為10dp
     */
    /**
     * 圓形模式
     */
    private static final int MODE_CIRCLE = 1;
    /**
     * 普通模式
     */
    private static final int MODE_NONE = 0;
    /**
     * 圓角模式
     */
    private static final int MODE_ROUND = 2;
    /**
     * 圓角半徑
     */
    private int currRound = dp2px(10);
    /**
     * 畫筆
     */
    private Paint mPaint;
    /**
     * 默認(rèn)是普通模式
     */
    private int currMode = 0;

    public ARoundImageView(Context context) {
        this(context,null);
    }

    public ARoundImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ARoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        obtainStyledAttrs(context, attrs, defStyleAttr);
        initViews();
    }

    private void obtainStyledAttrs(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ARoundImageView, defStyleAttr, 0);
        currMode = a.hasValue(R.styleable.ARoundImageView_type) ? a.getInt(R.styleable.ARoundImageView_type, MODE_NONE) : MODE_NONE;
        currRound = a.hasValue(R.styleable.ARoundImageView_radius) ? a.getDimensionPixelSize(R.styleable.ARoundImageView_radius, currRound) : currRound;
        a.recycle();
    }

    private void initViews() {
        //ANTI_ALIAS_FLAG 用于繪制時抗鋸齒
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
    }


    /**
     * 當(dāng)模式為圓形模式的時候,我們強制讓寬高一致
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (currMode == MODE_CIRCLE) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int result = Math.min(getMeasuredHeight(), getMeasuredWidth());
            // 此方法必須由{@link#onMeasure(int,int)}調(diào)用,以存儲已測量的寬度和測量的高度。
            // 如果不這樣做,將在測量時觸發(fā)異常。
            setMeasuredDimension(result, result);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        //獲取ImageView圖片資源
        Drawable mDrawable = getDrawable();
        //獲取Matrix對象
        Matrix mDrawMatrix = getImageMatrix();
        if (mDrawable == null) {
            return;
        }
        if (mDrawable.getIntrinsicWidth() == 0 || mDrawable.getIntrinsicHeight() == 0) {
            return;
        }
        if (mDrawMatrix == null && getPaddingTop() == 0 && getPaddingLeft() == 0) {
            mDrawable.draw(canvas);
        } else {
            final int saveCount = canvas.getSaveCount();
            canvas.save();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                if (getCropToPadding()) {
                    final int scrollX = getScrollX();
                    final int scrollY = getScrollY();
                    canvas.clipRect(scrollX + getPaddingLeft(), scrollY + getPaddingTop(),
                            scrollX + getRight() - getLeft() - getPaddingRight(),
                            scrollY + getBottom() - getTop() - getPaddingBottom());
                }
            }
            canvas.translate(getPaddingLeft(), getPaddingTop());
            switch (currMode){
                case MODE_CIRCLE:
                    Bitmap bitmap1 = drawable2Bitmap(mDrawable);
                    mPaint.setShader(new BitmapShader(bitmap1, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
                    canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2, mPaint);
                    break;
                case MODE_ROUND:
                    Bitmap bitmap2 = drawable2Bitmap(mDrawable);
                    mPaint.setShader(new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
                    canvas.drawRoundRect(new RectF(getPaddingLeft(), getPaddingTop(),
                                    getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()),
                            currRound, currRound, mPaint);
                    break;
                case MODE_NONE:
                default:
                    if (mDrawMatrix != null) {
                        canvas.concat(mDrawMatrix);
                    }
                    mDrawable.draw(canvas);
                    break;
            }
            canvas.restoreToCount(saveCount);
        }
    }

    /**
     * drawable轉(zhuǎn)換成bitmap
     */
    private Bitmap drawable2Bitmap(Drawable drawable) {
        if (drawable == null) {
            return null;
        }
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        //根據(jù)傳遞的scaleType獲取matrix對象,設(shè)置給bitmap
        Matrix matrix = getImageMatrix();
        if (matrix != null) {
            canvas.concat(matrix);
        }
        drawable.draw(canvas);
        return bitmap;
    }

    private int dp2px(float value) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                value, getResources().getDisplayMetrics());
    }
}

關(guān)于其他內(nèi)容介紹 01.關(guān)于博客匯總鏈接

1.技術(shù)博客匯總

2.開源項目匯總

3.生活博客匯總

4.喜馬拉雅音頻匯總

5.其他匯總

02.關(guān)于我的博客

我的個人站點:www.yczbj.org,www.ycbjie.cn

github:https://github.com/yangchong211

知乎:https://www.zhihu.com/people/...

簡書:http://www.jianshu.com/u/b7b2...

csdn:http://my.csdn.net/m0_37700275

喜馬拉雅聽書:http://www.ximalaya.com/zhubo...

開源中國:https://my.oschina.net/zbj161...

泡在網(wǎng)上的日子:http://www.jcodecraeer.com/me...

郵箱:[email protected]

阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV

segmentfault頭條:https://segmentfault.com/u/xi...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/77330.html

相關(guān)文章

  • ImageView 使用詳解

    極力推薦文章:歡迎收藏Android 干貨分享 showImg(https://segmentfault.com/img/remote/1460000019975020); 閱讀五分鐘,每日十點,和您一起終身學(xué)習(xí),這里是程序員Android 本篇文章主要介紹 Android 開發(fā)中的部分知識點,通過閱讀本篇文章,您將收獲以下內(nèi)容: 一、ImageView 的繼承關(guān)系二、ImageView 常用方...

    shery 評論0 收藏0
  • Drawable與 Bitmap 轉(zhuǎn)換總結(jié)

    摘要:進行縮放然后比對進行縮放調(diào)用中轉(zhuǎn)換成創(chuàng)建操作圖片用的對象計算縮放比例設(shè)置縮放比例建立新的,其內(nèi)容是對原的縮放后的圖至此,本篇已結(jié)束,如有不對的地方,歡迎您的建議與指正。同時期待您的關(guān)注,感謝您的閱讀,謝謝 showImg(https://segmentfault.com/img/remote/1460000019975019?w=157&h=54); 極力推薦文章:歡迎收藏Androi...

    snifes 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<