Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习

作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985
QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing/

Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习

大家都知道。现在好多头像都是圆形的,不再是以前的正方形或者长方形。
因此今天给大家带来的就是如何制作一个圆形头像。下面是效果图:
这里写图片描述
当然利用一个自定义View集成ImageView即可。

1package com.qq986945193.zoomimageviewrounddemo; 2 3import android.content.Context; 4import android.content.res.TypedArray; 5import android.graphics.Bitmap; 6import android.graphics.Bitmap.Config; 7import android.graphics.Canvas; 8import android.graphics.Paint; 9import android.graphics.PorterDuff.Mode; 10import android.graphics.PorterDuffXfermode; 11import android.graphics.Rect; 12import android.graphics.drawable.BitmapDrawable; 13import android.graphics.drawable.Drawable; 14import android.graphics.drawable.NinePatchDrawable; 15import android.util.AttributeSet; 16import android.widget.ImageView; 17 18/** * 微博:http://weibo.com/mcxiaobing * ============================================================================ * Copyright (c) 2015-2016 QQ986945193 All rights reserved. * ---------------------------------------------------------------------------- * 类名:自定义圆形头像View * ---------------------------------------------------------------------------- * 功能描述:http://blog.csdn.net/qq_21376985 * ---------------------------------------------------------------------------- */ 19 20public class RoundImageView extends ImageView { 21 private int mBorderThickness = 0; 22 private Context mContext; 23 private int defaultColor = 0xFFFFFFFF; 24 // 如果只有其中一个有值,则只画一个圆形边框 25 private int mBorderOutsideColor = 0;// 图片的外边界 26 private int mBorderInsideColor = 0;// 图片的内边界 27 // 控件默认长、宽 28 private int defaultWidth = 0; 29 private int defaultHeight = 0; 30 31 public RoundImageView(Context context) { 32 super(context); 33 mContext = context; 34 } 35 36 public RoundImageView(Context context, AttributeSet attrs) { 37 super(context, attrs); 38 mContext = context; 39 setCustomAttributes(attrs); 40 } 41 42 public RoundImageView(Context context, AttributeSet attrs, int defStyle) { 43 super(context, attrs, defStyle); 44 mContext = context; 45 setCustomAttributes(attrs); 46 } 47 48 private void setCustomAttributes(AttributeSet attrs) { 49 TypedArray a = mContext.obtainStyledAttributes(attrs, 50 R.styleable.RoundImageView); 51 // 边界的宽度 52 mBorderThickness = a.getDimensionPixelSize( 53 R.styleable.RoundImageView_border_thickness, 0); 54 // 外边界的颜色 55 mBorderOutsideColor = a.getColor( 56 R.styleable.RoundImageView_border_outside_color, defaultColor); 57 // 内边界的颜色 58 mBorderInsideColor = a.getColor( 59 R.styleable.RoundImageView_border_inside_color, defaultColor); 60 } 61 62 @Override 63 protected void onDraw(Canvas canvas) { 64 Drawable drawable = getDrawable(); 65 if (drawable == null) { 66 return; 67 } 68 69 if (getWidth() == 0 || getHeight() == 0) { 70 return; 71 } 72 this.measure(0, 0); 73 if (drawable.getClass() == NinePatchDrawable.class) 74 return; 75 Bitmap b = ((BitmapDrawable) drawable).getBitmap(); 76 Bitmap bitmap = b.copy(Config.ARGB_8888, true); 77 if (defaultWidth == 0) { 78 defaultWidth = getWidth(); 79 } 80 if (defaultHeight == 0) { 81 defaultHeight = getHeight(); 82 } 83 // 保证重新读取图片后不会因为图片大小而改变控件宽、高的大小(针对宽、高为wrap_content布局的imageview,但会导致margin无效) 84 // if (defaultWidth != 0 && defaultHeight != 0) { 85 // LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( 86 // defaultWidth, defaultHeight); 87 // setLayoutParams(params); 88 // } 89 90 int radius = 0; 91 if (mBorderInsideColor != defaultColor 92 && mBorderOutsideColor != defaultColor) {// 定义画两个边框,分别为外圆边框和内圆边框 93 radius = (defaultWidth < defaultHeight ? defaultWidth 94 : defaultHeight) / 2 - 2 * mBorderThickness; 95 // 画内圆 96 drawCircleBorder(canvas, radius + mBorderThickness / 2, 97 mBorderInsideColor); 98 // 画外圆 99 drawCircleBorder(canvas, radius + mBorderThickness 100 + mBorderThickness / 2, mBorderOutsideColor); 101 } else if (mBorderInsideColor != defaultColor 102 && mBorderOutsideColor == defaultColor) {// 定义画一个边框 103 radius = (defaultWidth < defaultHeight ? defaultWidth 104 : defaultHeight) / 2 - mBorderThickness; 105 drawCircleBorder(canvas, radius + mBorderThickness / 2, 106 mBorderInsideColor); 107 } else if (mBorderInsideColor == defaultColor 108 && mBorderOutsideColor != defaultColor) {// 定义画一个边框 109 radius = (defaultWidth < defaultHeight ? defaultWidth 110 : defaultHeight) / 2 - mBorderThickness; 111 drawCircleBorder(canvas, radius + mBorderThickness / 2, 112 mBorderOutsideColor); 113 } else {// 没有边框 114 radius = (defaultWidth < defaultHeight ? defaultWidth 115 : defaultHeight) / 2; 116 } 117 Bitmap roundBitmap = getCroppedRoundBitmap(bitmap, radius); 118 canvas.drawBitmap(roundBitmap, defaultWidth / 2 - radius, defaultHeight 119 / 2 - radius, null); 120 } 121 122 /** * 获取裁剪后的圆形图片 * * http://blog.csdn.net/qq_21376985 * @param radius * 半径 */ 123 public Bitmap getCroppedRoundBitmap(Bitmap bmp, int radius) { 124 Bitmap scaledSrcBmp; 125 int diameter = radius * 2; 126 127 // 为了防止宽高不相等,造成圆形图片变形,因此截取长方形中处于中间位置最大的正方形图片 128 int bmpWidth = bmp.getWidth(); 129 int bmpHeight = bmp.getHeight(); 130 int squareWidth = 0, squareHeight = 0; 131 int x = 0, y = 0; 132 Bitmap squareBitmap; 133 if (bmpHeight > bmpWidth) {// 高大于宽 134 squareWidth = squareHeight = bmpWidth; 135 x = 0; 136 y = (bmpHeight - bmpWidth) / 2; 137 // 截取正方形图片 138 squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, 139 squareHeight); 140 } else if (bmpHeight < bmpWidth) {// 宽大于高 141 squareWidth = squareHeight = bmpHeight; 142 x = (bmpWidth - bmpHeight) / 2; 143 y = 0; 144 squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, 145 squareHeight); 146 } else { 147 squareBitmap = bmp; 148 } 149 150 if (squareBitmap.getWidth() != diameter 151 || squareBitmap.getHeight() != diameter) { 152 scaledSrcBmp = Bitmap.createScaledBitmap(squareBitmap, diameter, 153 diameter, true); 154 155 } else { 156 scaledSrcBmp = squareBitmap; 157 } 158 Bitmap output = Bitmap.createBitmap(scaledSrcBmp.getWidth(), 159 scaledSrcBmp.getHeight(), Config.ARGB_8888); 160 Canvas canvas = new Canvas(output); 161 162 Paint paint = new Paint(); 163 Rect rect = new Rect(0, 0, scaledSrcBmp.getWidth(), 164 scaledSrcBmp.getHeight()); 165 166 paint.setAntiAlias(true); 167 paint.setFilterBitmap(true); 168 paint.setDither(true); 169 canvas.drawARGB(0, 0, 0, 0); 170 canvas.drawCircle(scaledSrcBmp.getWidth() / 2, 171 scaledSrcBmp.getHeight() / 2, scaledSrcBmp.getWidth() / 2, 172 paint); 173 paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 174 canvas.drawBitmap(scaledSrcBmp, rect, rect, paint); 175 // bitmap回收(recycle导致在布局文件XML看不到效果) 176 // bmp.recycle(); 177 // squareBitmap.recycle(); 178 // scaledSrcBmp.recycle(); 179 bmp = null; 180 squareBitmap = null; 181 scaledSrcBmp = null; 182 return output; 183 } 184 185 /** * 边缘画圆 * * http://blog.csdn.net/qq_21376985 */ 186 private void drawCircleBorder(Canvas canvas, int radius, int color) { 187 Paint paint = new Paint(); 188 /* 去锯齿 */ 189 paint.setAntiAlias(true); 190 paint.setFilterBitmap(true); 191 paint.setDither(true); 192 paint.setColor(color); 193 /* 设置paint的 style 为STROKE:空心 */ 194 paint.setStyle(Paint.Style.STROKE); 195 /* 设置paint的外框宽度 */ 196 paint.setStrokeWidth(mBorderThickness); 197 canvas.drawCircle(defaultWidth / 2, defaultHeight / 2, radius, paint); 198 } 199 200}

然后我们需要在布局中引用。下面是布局的一个引用,其实很简单,就和咱们
引用自定义View一模一样。由于它继承了ImageView。所以,方法大致相同。

1 <com.qq986945193.zoomimageviewrounddemo.RoundImageView 2 android:layout_width="100dp" 3 android:layout_height="100dp" 4 android:layout_centerInParent="true" 5 android:scaleType="fitCenter" 6 android:src="@drawable/img" />

当然还有,我们写了一个样式,所以需要在styles样式中添加:

1 <!-- 圆形ImageView --> 2 <declare-styleable name="RoundImageView"> 3 <attr name="border_thickness" format="dimension" /> 4 <attr name="border_inside_color" format="color" /> 5 <attr name="border_outside_color" format="color" /> 6 </declare-styleable>

OK,这样,圆形的的效果就能出来了,是不是很简单呢?当然,自定义View那一块想了解的可以深入。毕竟,你只会用,看不懂源代码也是不太好吧?是不是呢?
(Eclipse版本)源代码传送门:
http://download.csdn.net/detail/qq_21376985/9599249
(Android Studio版本)源代码传送门:
https://github.com/QQ986945193/DavidZoomImageViewRoundDemo

点赞
收藏

评论区

加载中...

相关推荐

java freemarker遍历树形菜单(导航栏菜单)

本人本人首发为csnd:http://blog.csdn.net/qq\_32196937/article/details/78793269(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fqq_32196937%2Farticle%2Fdetails%2

javafx实现打砖块游戏

今天学习了一下JavaFX游戏部分参考博客:http://blog.csdn.net/ml3947(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fml3947)本人源码地址:http://git.oschina.net/flyfox/Game

MQTT

源博客地址:http://blog.csdn.net/pipinet123(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fpipinet123)MQTT交流群:221405150面向群

Jetson TX1开发笔记(六):V4L2+OpenCV3.1以MJPG格式读取USB摄像头图像并实时显示

转载请注明作者和出处:http://blog.csdn.net/c406495762(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fc406495762)嵌入式平台(Target):JestonTX1OpenCV:

Java Mail

转载请注明出处:http://blog.csdn.net/qq\_26525215本文源自【大学之旅\_谙忆的博客(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fqq_26525215)】JavaMailAPI简介:

Android Hook框架adbi的分析(2)

本文博客地址:http://blog.csdn.net/qq1084283172/article/details/74452308(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fblog.csdn.net%2Fqq1084283172%2Farticle%2Fdetails%2F744