Android 自定義圓形頭像
Android 自定義圓形頭像
先上效果圖,如下:
這是有邊框的圓形ImageView的效果圖,如果想沒有邊框或者改變邊框的顏色都可以通過程式碼進行設定,下面直接上程式碼:
package com.example.admin.viewtest;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
/**
* 此類實現了圓形ImageView的功能
*/
public class CircleImageView extends View {
private Bitmap mBitmap;
private int mLineColor;
private int mLineWidth;
private Paint mPaint = new Paint();
private Context mContext;
public CircleImageView(Context context) {
super(context);
init(context, null);
}
public CircleImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
this.mContext = context;
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView);
BitmapDrawable drawable = (BitmapDrawable) ta.getDrawable(R.styleable.CircleImageView_src);
if (drawable != null)
mBitmap = drawable.getBitmap();
mLineColor = ta.getColor(R.styleable.CircleImageView_line_color, Color.WHITE);
mLineWidth = (int) ta.getDimension(R.styleable.CircleImageView_line_width, 0);
squareBitmap();
ta.recycle();
mPaint.setAntiAlias(true);
mPaint.setColor(mLineColor);
mPaint.setStrokeWidth(mLineWidth);
}
/**
* 將圖片處理為正方形圖片
*/
private void squareBitmap() {
if (mBitmap != null && mBitmap.getWidth() != mBitmap.getHeight()) {
int wh = Math.min(mBitmap.getWidth(), mBitmap.getHeight());
int num = Math.abs((mBitmap.getWidth() - mBitmap.getHeight()) / 2);
if (mBitmap.getHeight() >= mBitmap.getWidth()) {
mBitmap = Bitmap.createBitmap(mBitmap, 0, num, wh, wh);
} else {
mBitmap = Bitmap.createBitmap(mBitmap, num, 0, wh, wh);
}
}
}
@Override
public void draw(Canvas canvas) {
if (mBitmap != null) {
int w = getWidth() - getPaddingLeft() - getPaddingRight();
int h = getHeight() - getPaddingTop() - getPaddingBottom();
int bw = mBitmap.getWidth();
/**
* 根據畫布大小縮放圖片
*/
Matrix matrix = new Matrix();
if (w >= h) {
matrix.setScale(h / (float) bw, h / (float) bw);
} else {
matrix.setScale(w / (float) bw, w / (float) bw);
}
mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, bw, bw, matrix, true);
int width = 0;
int left;
int top;
/**
* 確定圖片的位置,這裡考慮了設定的padding,如果不處理padding的值,那麼設定的padding將失效
*/
if (mBitmap != null)
width = mBitmap.getWidth();
if (w >= h) {
left = getPaddingLeft() + Math.abs((w - h) / 2);
top = getPaddingTop();
} else {
left = getPaddingLeft();
top = getPaddingTop() + Math.abs((w - h) / 2);
}
canvas.drawBitmap(createCircleImage(mBitmap, width), left, top, mPaint);
mPaint.setColor(mLineColor);
mPaint.setStrokeWidth(mLineWidth);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(true);
canvas.drawCircle((width / 2) + left, width / 2 + top, width / 2 - mLineWidth, mPaint);
}
}
/**
* 繪製圓形圖片
*
* @param source
* @param min
* @return
*/
private Bitmap createCircleImage(Bitmap source, int min) {
Paint p = new Paint();
p.setAntiAlias(true);
Bitmap target = Bitmap.createBitmap(min, min, Bitmap.Config.ARGB_8888);
/**
* 產生一個同樣大小的畫布
*/
Canvas canvas = new Canvas(target);
/**
* 首先繪製圓形
*/
canvas.drawCircle(min / 2, min / 2, min / 2 - mLineWidth, p);
/**
* 使用SRC_IN,參考上面的說明
*/
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
/**
* 繪製圖片
*/
canvas.drawBitmap(source, 0, 0, p);
return target;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMeasureMode = MeasureSpec.getMode(widthMeasureSpec);
int widthMeasureSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMeasureMode = MeasureSpec.getMode(heightMeasureSpec);
int heightMeasureSize = MeasureSpec.getSize(heightMeasureSpec);
int pd = getPaddingBottom();
int pt = getPaddingTop();
int pl = getPaddingLeft();
int pr = getPaddingRight();
int width = 0;
int height = 0;
/**
* 獲取設定的圖片的寬高
*/
if (mBitmap != null) {
width = mBitmap.getWidth();
height = mBitmap.getHeight();
}
/**
*當寬、高設定為wrap_content時,Mode為MeasureSpec.AT_MOST最大模式;
*當寬、高設定為match_parent或者具體的值時,Mode為MeasureSpec.EXACTLY精確模式;
*在測量View的寬、高時,需要對padding做處理,不然設定的padding將會失效
*/
if (widthMeasureMode == MeasureSpec.AT_MOST && heightMeasureMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(width + pl + pr, height + pd + pt);
} else if (widthMeasureMode == MeasureSpec.AT_MOST && heightMeasureMode == MeasureSpec.EXACTLY) {
setMeasuredDimension(width + pl + pr, heightMeasureSize);
} else if (widthMeasureMode == MeasureSpec.EXACTLY && heightMeasureMode == MeasureSpec.EXACTLY) {
setMeasuredDimension(widthMeasureSize, heightMeasureSize);
} else if (widthMeasureMode == MeasureSpec.EXACTLY && heightMeasureMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthMeasureSize, height + pd + pt);
}
}
public void setImageBitmap(Bitmap bitmap) {
recycleBitmap();
this.mBitmap = bitmap;
squareBitmap();
invalidate();
}
public void setImageDrawable(Drawable drawable) {
setImageBitmap(drawable == null ? null : drawableToBitmap(drawable));
}
public void setImageResource(int resId) {
setImageDrawable(ContextCompat.getDrawable(mContext, resId));
}
public void setLineColorResource(int resId) {
setLineColor(ContextCompat.getColor(mContext, resId));
}
public void setLineColor(int color) {
mLineColor = color;
invalidate();
}
/**
* 設定線的寬度
*
* @param width 這個寬度的單位是px
*/
public void setLineWidth(int width) {
mLineWidth = width;
invalidate();
}
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else if (drawable instanceof NinePatchDrawable) {
// 取 drawable 的長寬
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
// 取 drawable 的顏色格式
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
// 建立對應 bitmap
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
// 建立對應 bitmap 的畫布
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
// 把 drawable 內容畫到畫布中
drawable.draw(canvas);
return bitmap;
} else {
return null;
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
recycleBitmap();
}
/**
* 釋放圖片資源
*/
private void recycleBitmap() {
if (mBitmap != null) {
mBitmap.recycle();
mBitmap = null;
}
}
}
上面就是自定義View的全部程式碼了,程式碼的關鍵位置都寫了註釋,同時也很簡單,相信大家一看就懂了,所以不多做解釋。本自定義圓形ImageView為了方便在佈局中設定圖片、邊框顏色和邊框寬度,在attrs.xml
檔案中新增了以下屬性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleImageView">
<attr name="src" format="reference"></attr>
<attr name="line_color" format="color"></attr>
<attr name="line_width" format="dimension"></attr>
</declare-styleable>
</resources>
同時在初始化控制元件的時候獲取了設定的屬性:
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView);
BitmapDrawable drawable = (BitmapDrawable) ta.getDrawable(R.styleable.CircleImageView_src);
if (drawable != null)
mBitmap = drawable.getBitmap();
mLineColor = ta.getColor(R.styleable.CircleImageView_line_color, Color.WHITE);
mLineWidth = (int) ta.getDimension(R.styleable.CircleImageView_line_width, 0);
ta.recycle();
這裡需要注意在使用完TypedArray 之後,需要及時的呼叫ta.recycle()釋放資源。
以上就是自定義圓形ImageView的所有程式碼和說明了,大家有不懂的歡迎留言。
相關文章
- Android自定義圓形頭像Android
- 自定義ImageView完成圓形頭像自定義View
- 自定義圓形ImageView(仿QQ頭像)View
- Android之圓形頭像裁切Android
- Android 自定義圓形旋轉進度條,仿微博頭像載入效果Android
- 自定義頭像圓角控制元件控制元件
- Android 圓形頭像 自己動手Android
- Flutter 圓形/圓角頭像Flutter
- Android自定義圓形進度條Android
- 《Android開發卷——設定圓形頭像,Android擷取圓形圖片》Android
- Android 圓形頭像 相簿和拍照裁剪選取Android
- android圓形頭像的選擇和剪下並儲存出圓形圖片Android
- Android圓形圖片--自定義控制元件Android控制元件
- 基於 GD 庫生成圓形頭像
- android裁剪圓型頭像Android
- 自定義圓形進度條
- Android自定義圓形進度條原始碼解析Android原始碼
- CircleImageView 圓形圖片頭像實現View
- Android自定義設定圓形圖片控制元件Android控制元件
- Android自定義圓形進度條實現程式碼Android
- Android進階 自定義View(三)圓形刻度進度條AndroidView
- canvas之自定義頭像功能實現Canvas
- Android自定義View——從零開始實現圓形進度條AndroidView
- 微信小程式獲取使用者頭像修改為圓形微信小程式
- Android自定義View之圖片外形特效——輕鬆實現圓角和圓形圖片AndroidView特效
- Android – 自定義Loading圓點Android
- Android自定義控制元件系列之圓形進度條的實現Android控制元件
- 自定義View實現箭頭沿圓轉動View
- Kotlin 背景圓頭像圖Kotlin
- 【Android】自定義樹形控制元件Android控制元件
- Android 自定義 View:包含多種狀態的下載用圓形進度條AndroidView
- 自定義圓形View:實現跟隨手指移動的小球View
- Android 高仿微信頭像擷取 打造不一樣的自定義控制元件Android控制元件
- Android 圓角、圓形 ImageView 實現AndroidView
- 使用 RoundedBitmapDrawable 建立圓角頭像詳解
- Android 自定義控制元件一 帶圓形進度的按鈕 ControlButton2Android控制元件
- 自定義隨機顏色的圓形小球view隨手指移動隨機View
- Android自定義控制元件實現一個帶文字與數字的圓形進度條Android控制元件