android-圆形头像
2016-05-13 16:04
429 查看
现在越来越多的应用都会用到圆形的头像,这样会试界面看起来比较美观,最常用的应用就是QQ了。其实把一张矩形的图片剪裁为圆形的图片原理还是比较简单的,就是先画圆然后再绘制图片,然后取两个图形交叉的部分。
Utils是工具类,onLoadImage是加载网络图片
getCroppedCircleBitmap是裁剪成圆形
MainActivity类
布局只有一个ImageView的控件。
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ImageView;
@SuppressLint("DrawAllocation")
public class CircleImageView extends ImageView{
public static final int TYPE_CRICLE = 1;
public static final int TYPE_ROUND = 0;
private Matrix matrix;
private Paint paint;
private int borderRadius;
private int type;
private int radius;
private int width;
private RectF rectF;
public CircleImageView(Context context, AttributeSet attrs) {
super(context, attrs);
inital(context,attrs);
}
private void inital(Context context, AttributeSet attrs) {
matrix = new Matrix();
paint = new Paint();
//无锯齿
paint.setAntiAlias(true);
borderRadius = dp2px(10); //设置圆角的默认值
type = TYPE_ROUND; //默认为方形
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (type == TYPE_CRICLE) {
//如果为圆形则强制改变长宽一直 并以较小的值为准
width = Math.min(getMeasuredWidth(), getMeasuredHeight());
radius = width / 2;
setMeasuredDimension(width, width);
}
Drawable drawable = getDrawable();
if (drawable == null) {
return ;
}
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
//指定着色器 在指定区域内作图
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
float scale = 1.0f;
int viewWidth = getWidth();
int viewHeight = getHeight();
int drawableWidth = bitmap.getWidth();
int drawableHeight = bitmap.getHeight();
if (type == TYPE_CRICLE) {
int size = Math.min(drawableHeight, drawableWidth);
scale = viewWidth * 1.0f / size;
}else {
scale = Math.max(viewWidth * 1.0f / drawableWidth, viewHeight * 1.0f / drawableHeight);
}
// if (drawableWidth * viewHeight > drawableHeight * viewWidth) {
// dx = (viewWidth - drawableWidth * scale ) * 0.5f;
// }else {
// dx = (viewHeight - drawableHeight* scale ) * 0.5f;
// }
matrix.setScale(scale, scale);
// matrix.postTranslate((int) (dx + 0.5f), (int ) (dy + 0.5f));
bitmapShader.setLocalMatrix(matrix);
paint.setShader(bitmapShader);
}
@Override
protected void onDraw(Canvas canvas) {
if (getDrawable() == null) {
return;
}
if (type == TYPE_CRICLE) {
canvas.drawCircle(radius, radius, radius, paint);
}else {
canvas.drawRoundRect(rectF, borderRadius, borderRadius, paint);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (type == TYPE_ROUND) {
rectF = new RectF(0, 0, getWidth(), getHeight());
}
}
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
public void setBorderRadius(int borderRadius){
int px = dp2px(borderRadius);
if (px != this.borderRadius) {
this.borderRadius = px;
invalidate();
}
}
public void setType(int type){
if (this.type != type) {
this.type = type;
if (this.type != TYPE_CRICLE && this.type != TYPE_ROUND) {
this.type = TYPE_CRICLE; //默认为圆形
}
}
}
}
public static Bitmap getCroppedCircleBitmap(Bitmap bitmap){ Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); //裁剪出传入图片的大小一个矩形 final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); Canvas canvas = new Canvas(output); final Paint paint = new Paint(); paint.setAntiAlias(true); int halfWidth = bitmap.getWidth()/5; int halfHeight = bitmap.getHeight()/5; //画圆 canvas.drawCircle(halfWidth, halfHeight, Math.max(halfWidth, halfHeight), paint); //设置为取两层图像交集部门,只显示上层图像 所以只显示圆 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap,rect,rect,paint); return output; }以下是一个从网络上获取一张图片然后裁剪成一个圆形的例子:
Utils是工具类,onLoadImage是加载网络图片
getCroppedCircleBitmap是裁剪成圆形
public class Utils {
public static void onLoadImage(final URL bitmapUrl, final OnLoadImageListener onLoadImageListener) {
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
onLoadImageListener.OnLoadImage((Bitmap) msg.obj, null);
}
};
new Thread(new Runnable() {
@Override
public void run() {
URL imageUrl = bitmapUrl;
try {
HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
InputStream inputStream = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
Message msg = new Message();
msg.obj = bitmap;
handler.sendMessage(msg); //图片加载完成调用接口
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
public static Bitmap getCroppedCircleBitmap(Bitmap bitmap){ Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); //裁剪出传入图片的大小一个矩形 final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); Canvas canvas = new Canvas(output); final Paint paint = new Paint(); paint.setAntiAlias(true); int halfWidth = bitmap.getWidth()/5; int halfHeight = bitmap.getHeight()/5; //画圆 canvas.drawCircle(halfWidth, halfHeight, Math.max(halfWidth, halfHeight), paint); //设置为取两层图像交集部门,只显示上层图像 所以只显示圆 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap,rect,rect,paint); return output; }//图片加载完成的一个接口
public interface OnLoadImageListener {
void OnLoadImage(Bitmap bitmap, String bitmapPath);
}
}
MainActivity类
public class MainActivity extends Activity { private ImageView imageView; private URL url; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.circle_activity); imageView = (ImageView) findViewById(R.id.image); try { url = new URL("http://a.hiphotos.baidu.com/image/pic/item/f9dcd100baa1cd11daf25f19bc12c8fcc3ce2d46.jpg"); } catch (MalformedURLException e) { e.printStackTrace(); } Utils.onLoadImage(url, new Utils.OnLoadImageListener() { @Override public void OnLoadImage(Bitmap bitmap, String bitmapPath) { bitmap = Utils.getCroppedCircleBitmap(bitmap); imageView.setImageBitmap(bitmap); } }); } }
布局只有一个ImageView的控件。
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ImageView;
@SuppressLint("DrawAllocation")
public class CircleImageView extends ImageView{
public static final int TYPE_CRICLE = 1;
public static final int TYPE_ROUND = 0;
private Matrix matrix;
private Paint paint;
private int borderRadius;
private int type;
private int radius;
private int width;
private RectF rectF;
public CircleImageView(Context context, AttributeSet attrs) {
super(context, attrs);
inital(context,attrs);
}
private void inital(Context context, AttributeSet attrs) {
matrix = new Matrix();
paint = new Paint();
//无锯齿
paint.setAntiAlias(true);
borderRadius = dp2px(10); //设置圆角的默认值
type = TYPE_ROUND; //默认为方形
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (type == TYPE_CRICLE) {
//如果为圆形则强制改变长宽一直 并以较小的值为准
width = Math.min(getMeasuredWidth(), getMeasuredHeight());
radius = width / 2;
setMeasuredDimension(width, width);
}
Drawable drawable = getDrawable();
if (drawable == null) {
return ;
}
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
//指定着色器 在指定区域内作图
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
float scale = 1.0f;
int viewWidth = getWidth();
int viewHeight = getHeight();
int drawableWidth = bitmap.getWidth();
int drawableHeight = bitmap.getHeight();
if (type == TYPE_CRICLE) {
int size = Math.min(drawableHeight, drawableWidth);
scale = viewWidth * 1.0f / size;
}else {
scale = Math.max(viewWidth * 1.0f / drawableWidth, viewHeight * 1.0f / drawableHeight);
}
// if (drawableWidth * viewHeight > drawableHeight * viewWidth) {
// dx = (viewWidth - drawableWidth * scale ) * 0.5f;
// }else {
// dx = (viewHeight - drawableHeight* scale ) * 0.5f;
// }
matrix.setScale(scale, scale);
// matrix.postTranslate((int) (dx + 0.5f), (int ) (dy + 0.5f));
bitmapShader.setLocalMatrix(matrix);
paint.setShader(bitmapShader);
}
@Override
protected void onDraw(Canvas canvas) {
if (getDrawable() == null) {
return;
}
if (type == TYPE_CRICLE) {
canvas.drawCircle(radius, radius, radius, paint);
}else {
canvas.drawRoundRect(rectF, borderRadius, borderRadius, paint);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (type == TYPE_ROUND) {
rectF = new RectF(0, 0, getWidth(), getHeight());
}
}
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
public void setBorderRadius(int borderRadius){
int px = dp2px(borderRadius);
if (px != this.borderRadius) {
this.borderRadius = px;
invalidate();
}
}
public void setType(int type){
if (this.type != type) {
this.type = type;
if (this.type != TYPE_CRICLE && this.type != TYPE_ROUND) {
this.type = TYPE_CRICLE; //默认为圆形
}
}
}
}
相关文章推荐
- Android项目重构之路:实现篇
- android Highcharts绘图一些要点
- Android应用基础知识
- android 开发之 Junit单元测试
- Android FragmentManage FragmentTransaction介绍
- Android 中创建SharedPreferences工具类来保存状态,标志,数据等
- Android四大组件之BroadcastReceiver(广播)简单总结
- [Android]Android源码下载和编译
- 【Android】TypedArray和obtainStyledAttributes使用
- Android打包签名
- android获取短信验证码并自动填写的实现一
- 关于android无线连接的问题
- Android中Parcelable接口
- Android动态添加TextView
- Android系统上部署webservice
- Android广播的基本介绍
- Android 开发 之 JNI入门 - NDK从入门到精通
- Android Scroll分析
- Android : 巧用RadioGroup作为Tab切换的按钮
- Android项目重构之路:界面篇