圓形頭像很常用功能,於是想自己寫個自定義的圓形的view。搜索了一下,android中可以通過BitmapShader實現這個效果。
BitmapShader是Shader的子類,可以通過Paint.setShader(Shader shader)進行設置、
這裏我們只關注BitmapShader,構造方法:
bitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);
參數1:bitmap
參數2,參數3:TileMode;
TileMode的取值有三種:
CLAMP 拉伸
REPEAT 重複
MIRROR 鏡像
如果大家給電腦屏幕設置屏保的時候,如果圖片太小,可以選擇重複、拉伸、鏡像;
重複:就是橫向、縱向不斷重複這個bitmap
鏡像:橫向不斷翻轉重複,縱向不斷翻轉重複;
拉伸:這個和電腦屏保的模式應該有些不同,這個拉伸的是圖片最後的那一個像素;橫向的最後一個橫行像素,不斷的重複,縱項的那一列像素,不斷的重複;
首先現在values下新建attrs.xml,自定義屬性。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleImageView">
<attr name="mborder_color" format="color"></attr>
<attr name="mborder_width" format="dimension"></attr>
<attr name="msrc" format="reference"></attr>
</declare-styleable>
</resources>
CircleImageView.java
package com.sy.callme.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import com.sy.callme.R;
/**
* Created by SY on 2016/5/16.
*/
public class CircleImageView extends View {
private Bitmap bitmap;
private int borderWidth;
private Drawable drawable;
private int borderColor;
private int width;
private int height;
private Bitmap src;
private BitmapShader shader;
private Paint paint;
private int radius;
private int circleX;
private int circleY;
private Paint borderPaint;
public CircleImageView(Context context) {
super(context);
}
public CircleImageView(Context context, AttributeSet attrs) {
super(context, attrs);
//獲取自定義屬性
TypedArray type = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView);
borderColor = type.getColor(R.styleable.CircleImageView_mborder_color, 0);
borderWidth = type.getDimensionPixelSize(R.styleable.CircleImageView_mborder_width, 2);
drawable = type.getDrawable(R.styleable.CircleImageView_msrc);
//轉換爲bitmap
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
bitmap = bitmapDrawable.getBitmap();
}
private int measureHeight(int heightMeasureSpec) {
int size = MeasureSpec.getSize(heightMeasureSpec);
int sizeMode = MeasureSpec.getMode(heightMeasureSpec);
int result = 0;
if (sizeMode == MeasureSpec.EXACTLY) {
//如果是精確尺寸就直接返回結果
result = size;
} else {
//不是就尺寸設置最大爲200
result = 200;
if (sizeMode == MeasureSpec.AT_MOST) {
//如果是最大尺寸就返回實際尺寸和最大尺寸之中較小的
result = Math.min(result, size);
}
}
return result;
}
private int measureWidth(int widthMeasureSpec) {
int size = MeasureSpec.getSize(widthMeasureSpec);
int sizeMode = MeasureSpec.getMode(widthMeasureSpec);
int result = 0;
if (sizeMode == MeasureSpec.EXACTLY) {
//如果是精確尺寸就直接返回結果
result = size;
} else {
//如果是精確尺寸就直接返回結果
result = 200;
if (sizeMode == MeasureSpec.AT_MOST) {
//如果是最大尺寸就返回實際尺寸和最大尺寸之中較小的
result = Math.min(result, size);
}
}
return result;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = measureWidth(widthMeasureSpec);
height = measureHeight(heightMeasureSpec);
width = height = Math.min(width, height);
initView();//初始化畫筆參數
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(circleX, circleY, radius, paint);
canvas.drawCircle(circleX, circleY, radius, borderPaint);
}
private void initView() {
src = Bitmap.createScaledBitmap(bitmap, width, height, true);
shader = new BitmapShader(src, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint = new Paint();
paint.setShader(shader);//設置shader
radius = (width - borderWidth * 2) / 2;
circleX = (width) / 2;
circleY = (height) / 2;
borderPaint = new Paint();
borderPaint.setStyle(Paint.Style.STROKE);
borderPaint.setStrokeWidth(borderWidth);
borderPaint.setColor(borderColor);
borderPaint.setStrokeJoin(Paint.Join.ROUND);//接合處的圓滑
borderPaint.setStrokeCap(Paint.Cap.ROUND);//圓角的筆觸
}
public void setImageResoure(Drawable drawable) {
//轉換爲bitmap
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
bitmap = bitmapDrawable.getBitmap();
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint = new Paint();
paint.setShader(shader);
requestLayout();
invalidate();
}
}
首先獲取自定義屬性的值,然後在onMeasure方法裏獲得控件寬高,initView方法裏設置畫筆的參數,創建BitmapShader並給paint設置shader。最後在onDraw方法裏繪製就可以了。具體使用:
<com.sy.callme.view.CircleImageView
android:id="@+id/c_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginTop="20dp"
android:layout_gravity="center_horizontal"
app:mborder_color="#ff7700"
app:mborder_width="3dp"
app:msrc="@mipmap/touxiang" />
記得使用自定義view的自定義屬性需要在佈局文件中引入xmlns:app="http://schemas.android.com/apk/res-auto"
參考資料:Android自定義屬性時TypedArray的使用方法
Android學習筆記進階15之Shader渲染
Android學習筆記進階16之BitmapShader
詳解Paint的各種set方法