国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

khs1994 / 2049人閱讀

摘要:將當前狀態保存在堆棧,之后可以調用的平移旋轉錯切剪裁等操作。恢復為之前堆棧保存的狀態,防止后對執行的操作對后續的繪制有影響。

目錄介紹

1.Paint畫筆介紹

1.1 圖形繪制

1.2 文本繪制

2.Canvas畫布介紹

2.1 設置屬性

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旋轉

3.3 scale縮放

3.4 skew扭曲

4.RectF介紹

4.1 Rect簡單屬性

4.2 Rect父類的實現

4.3 Rect常用的一些方法

5.關于使用到這幾個屬性的自定義View

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

5.1 自定義輪播圖圓點

5.2 自定義圓環百分比進度條

好消息

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

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

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

1.Paint畫筆介紹

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

1.1 圖形繪制

常用的方法有這些

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

1.2 文本繪制

常用的方法有這些

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


2.Canvas畫布介紹

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

2.1 設置屬性

一般屬性有:

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

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

2.2 畫圖【重點】

畫圖部分

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

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

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

第二種通過new創建一個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);
    //實心圓弧 將圓心包含在內
    RectF rel2 = new RectF(50, 200, 150, 300);
    canvas.drawArc(rel2, 0, 135, true, paint);
    //設置空心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位置轉換】

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

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

3.1 translate平移 3.2 rorate旋轉

rorate旋轉

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);
    // 保存畫布狀態
    canvas.save();
    canvas.scale(0.5f, 0.5f);
    mPaint.setColor(Color.GREEN);
    canvas.drawRect(new Rect(0, 0, 800, 800), mPaint);
    // 畫布狀態回滾
    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簡單屬性

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

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

其中常用的構造方法如下所示

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父類的實現

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

對于equals方法,首先先對傳來的對象進行判空,類型判斷,再強轉成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常用的一些方法

獲取“寬”

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

獲取“高”

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

有效性的判斷

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

全部置0操作

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

設置參數方法,和構造函數的區別僅在于不會創建新對象

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

5.關于使用到這幾個屬性的自定義View

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

5.1 自定義輪播圖圓點

5.1.1 需求介紹

繪制圓環,一個實心中心圓,還有一個外圓環

此控件可以設置寬度和高度,可以設置顏色

5.1.2 思路介紹

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

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

3.2.3 然后分別繪制選中狀態和未選中狀態的圓

3.2.4 創建畫筆Paint,并且設置相關屬性,比如畫筆顏色,類型等

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

3.2.6 自定義一個是否選中狀態的方法,傳入布爾值是否選中,然后調用view中invalidate方法

5.1.3 代碼介紹

具體代碼如下所示:

/**
 * 
 *     @author yangchong
 *     blog  : https://github.com/yangchong211
 *     time  : 2016/5/18
 *     desc  : 紅點自定義控件
 *     revise: 建議設置紅點寬高一樣,否則是橢圓
 * 
*/ 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) { //設置paint相關屬性 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); //繪制指定的弧線,該弧線將被縮放以適應指定的橢圓形。 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); } /** * 設置是否選中 * @param isSelected isSelected */ public void setIsSelected(boolean isSelected) { this.isSelected = isSelected; //使整個視圖無效。如果視圖是可見的,則{@link#onDraw(android.Graphics.Canvas)}將在將來的某個時候被調用。 //調用該方法,會進行重新繪制,也就是調用onDraw方法 this.invalidate(); } }

5.2 自定義圓環百分比進度條

5.2.1 需求分析

1.業務需求:可以設置圓角,可以設置圓形,如果是圓角則必須設置半徑,默認圓角半徑為10dp

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

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

5.2.2 代碼介紹

代碼如下所示

public class ARoundImageView extends AppCompatImageView {

    /*
     *   Paint:畫筆
     *   Canvas:畫布
     *   Matrix:變換矩陣
     *
     *   業務需求:可以設置圓角,可以設置圓形,如果是圓角則必須設置半徑,默認圓角半徑為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;
    /**
     * 默認是普通模式
     */
    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);
    }


    /**
     * 當模式為圓形模式的時候,我們強制讓寬高一致
     */
    @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)}調用,以存儲已測量的寬度和測量的高度。
            // 如果不這樣做,將在測量時觸發異常。
            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轉換成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);
        //根據傳遞的scaleType獲取matrix對象,設置給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());
    }
}

關于其他內容介紹 01.關于博客匯總鏈接

1.技術博客匯總

2.開源項目匯總

3.生活博客匯總

4.喜馬拉雅音頻匯總

5.其他匯總

02.關于我的博客

我的個人站點: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...

泡在網上的日子:http://www.jcodecraeer.com/me...

郵箱:yangchong211@163.com

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

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77330.html

相關文章

  • ImageView 使用詳解

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

    shery 評論0 收藏0
  • Drawable與 Bitmap 轉換總結

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

    snifes 評論0 收藏0

發表評論

0條評論

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