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
- Android自定義圓形進度條Android
- Flutter 圓形/圓角頭像Flutter
- Android 圓形頭像 相簿和拍照裁剪選取Android
- 基於 GD 庫生成圓形頭像
- 微信頭像生成圓形邀請卡
- [-Flutter 自定義元件-] 圓形進度條Flutter元件
- 自定義圓形進度條控制元件控制元件
- Android自定義View之圖片外形特效——輕鬆實現圓角和圓形圖片AndroidView特效
- 【Android】自定義樹形控制元件Android控制元件
- Android 自定義 View:包含多種狀態的下載用圓形進度條AndroidView
- Kotlin 背景圓頭像圖Kotlin
- 自定義圓環
- 微信小程式獲取使用者頭像修改為圓形微信小程式
- Android 圓角、圓形 ImageView 實現AndroidView
- android opencv 前置攝像頭AndroidOpenCV
- android 開啟攝像頭Android
- Android呼叫攝像頭拍照Android
- 圓角頭像加360旋轉效果
- 使用 RoundedBitmapDrawable 建立圓角頭像詳解
- Android 開發:glide圓角,圓形,效率問題AndroidIDE
- win10系統怎麼設定登陸影像為圓形_win10將登入介面頭像設定為圓形教程Win10
- Android 圓形ProgressBar 改變顏色Android
- Android提供的攝像頭拍照Android
- android自定義view(自定義數字鍵盤)AndroidView
- 利用Xfermode 自定義形狀ViewView
- ios自定義圓環進度條iOS
- elementUI 2.0.11自定義表頭UI
- elementUI table 自定義表頭UI
- Android 自定義UI元件AndroidUI元件
- android 自定義鍵盤Android
- Android自定義View整合AndroidView
- Android自定義遮罩層Android遮罩
- 自定義Android鍵盤Android
- Android自定義OnTouch事件Android事件
- Android Reveal圓形Activity轉場動畫Android動畫
- [譯]Android的多攝像頭支援Android
- [譯] Android 的多攝像頭支援Android
- 基於 HTML5 的 WebGL 自定義 3D 攝像頭監控模型HTMLWeb3D模型