Android学习之仿QQ讨论组和微信群聊头像
来源:互联网 发布:u盘安装linux卡在scsi 编辑:程序博客网 时间:2024/04/30 17:36
这是自己总结的,希望对你们有帮助
1:先看效果
2:具体代码实现
2.1 直接粘代码
public class GroupView extends ImageView { /** 图片之间的距离 */ private int padding = 2; /** 圆角值 */ private int cornor = 0; private int width,height;; /** 头像模式 圆的 */ public static final int FACETYPE_CIRCLE = 1; /** 头像模式 方的 最多9个 */ public static final int FACETYPE_SQUARE = 2; private Context mContext; private int mViewType;//默认圆形 private Bitmap[] mBitmaps ; private int background; public GroupView(Context context,Bitmap[] bitmaps) { super(context); this.mBitmaps = bitmaps; } public GroupView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public GroupView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GroupView, defStyleAttr, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.GroupView_type: mViewType = a.getInt(R.styleable.GroupView_type, FACETYPE_CIRCLE); break; case R.styleable.GroupView_cornor: cornor = (int) a.getDimension(R.styleable.GroupView_cornor,0); break; case R.styleable.GroupView_padding: padding = (int) a.getDimension(R.styleable.GroupView_padding,3); case R.styleable.GroupView_backgroundGP: background = a.getColor(R.styleable.GroupView_backgroundGP,Color.parseColor("#DDDFD4")); break; default: break; } } a.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); } private int measureWidth(int widthMeasureSpec){ int widthMode = MeasureSpec.getMode(widthMeasureSpec); if (widthMode == MeasureSpec.AT_MOST) { width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); } else { width = MeasureSpec.getSize(widthMeasureSpec); } return width; } private int measureHeight(int heightMeasureSpec){ int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (heightMode == MeasureSpec.AT_MOST) { height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); } else { height = MeasureSpec.getSize(heightMeasureSpec); } return height; } @Override protected void onDraw(Canvas canvas) { // super.onDraw(canvas); Paint paint = new Paint(); canvas.drawBitmap(createGroupFace(mViewType, mContext, mBitmaps),0,0,paint); } public void setImageBitmaps(Bitmap[] bitmaps) { mBitmaps = bitmaps; } public void setImageBitmaps(List<Bitmap> bitmaps) { mBitmaps = bitmaps.toArray(new Bitmap[bitmaps.size()]); } public Bitmap createGroupFace(int type, Context context, Bitmap[] bitmapArray) { System.out.println("hiwhitley"+"type"+type); if (type == FACETYPE_CIRCLE) { return createGroupBitCircle(bitmapArray, context); } return createTogetherBit(bitmapArray, context); } private static Bitmap scaleBitmap(float paramFloat, Bitmap paramBitmap) { Matrix localMatrix = new Matrix(); localMatrix.postScale(paramFloat, paramFloat); return Bitmap.createBitmap(paramBitmap, 0, 0, paramBitmap.getWidth(), paramBitmap.getHeight(), localMatrix, true); } /** * 拼接群头像 圆形版的 * * @param bitmapArray * @param context * @return */ private Bitmap createGroupBitCircle(Bitmap[] bitmapArray, Context context) { if (bitmapArray.length < 1 && bitmapArray.length > 9) { return null; } // 先取一个获取宽和高 Bitmap tempBitmap = (Bitmap) bitmapArray[0]; if (tempBitmap == null) { return null; } // 画布的宽 int tempWidth = width; // 画布的高 int tempHeight = height; Bitmap canvasBitmap = Bitmap.createBitmap(tempWidth, tempHeight, Bitmap.Config.ARGB_8888); Canvas localCanvas = new Canvas(canvasBitmap); localCanvas.drawColor(background); JoinBitmaps.join(localCanvas, Math.min(tempWidth, tempHeight), Arrays.asList(bitmapArray)); return canvasBitmap; } /** * 拼接群头像 * * @param paramList * @param context * @return 头像本地路径 */ @SuppressWarnings("unused") private Bitmap createTogetherBit(Bitmap[] paramList, final Context context) { if (paramList.length < 1 && paramList.length > 9) { return null; } // 先取一个获取宽和高 Bitmap tempBitmap = (Bitmap) paramList[0]; if (tempBitmap == null) { return null; } // 画布的宽 int tempWidth = width; // 画布的高 int tempHeight = height; // 创建一个空格的bitmap Bitmap canvasBitmap = Bitmap.createBitmap(tempWidth, tempHeight, Bitmap.Config.ARGB_8888); // 头像的数量 int bitmapCount = paramList.length; Canvas localCanvas = new Canvas(canvasBitmap); localCanvas.drawColor(background); int colum = 0; if (bitmapCount > 1 && bitmapCount < 5) { colum = 2; } else if (bitmapCount > 4 && bitmapCount < 10) { colum = 3; } else { colum = 1; } float scale = 1.0F / colum; // 根据列数缩小 Bitmap scaledBitmap = scaleBitmap(scale, tempBitmap); if (padding > 0) { padding = dip2px(context, padding); // 如果有内边距 再次缩小 float paddingScale = (float) (tempWidth - (colum + 1) * padding) / colum / scaledBitmap.getWidth(); scaledBitmap = scaleBitmap(paddingScale, scaledBitmap); scale = scale * paddingScale; } // 第一行的 头像个数 int topRowCount = bitmapCount % colum; // 满行的行数 int rowCount = bitmapCount / colum; if (topRowCount > 0) { // 如果第一行头像个数大于零 行数加1 rowCount++; } else if (topRowCount == 0) { // 6 或者 9 第一行头像个数和列数一致 topRowCount = colum; } // 缩小后头像的宽 int scaledWidth = scaledBitmap.getWidth(); // 缩小后头像的高 int scaledHeight = scaledBitmap.getHeight(); // 第一个头像与画布顶部的距离 int firstTop = ((tempHeight - (rowCount * scaledHeight + (rowCount + 1) * padding)) / 2) + padding; // 第一个头像与画布左部的距离 int firstLeft = ((tempWidth - (topRowCount * scaledWidth + (topRowCount + 1) * padding)) / 2) + padding; for (int i = 0; i < paramList.length; i++) { if (i == 9) {// 达到上限 停止 break; } // 按照最终压缩比例压缩 Bitmap bit = scaleBitmap(scale, (Bitmap) paramList[i]); if (cornor > 0) { // 圆角化 bit = GetRoundedCornerBitmap(bit); } localCanvas.drawBitmap(bit, firstLeft, firstTop, null); firstLeft += (scaledWidth + padding); if (i == topRowCount - 1 | tempWidth - firstLeft < scaledWidth) { firstTop += (scaledHeight + padding); firstLeft = padding; } bit.recycle(); } // 重置padding //padding = 2; localCanvas.save(Canvas.ALL_SAVE_FLAG); localCanvas.restore(); return canvasBitmap; } /** * 圆角 * * @param bitmap * @return */ private Bitmap GetRoundedCornerBitmap(Bitmap bitmap) { try { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight())); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(Color.BLACK); canvas.drawRoundRect(rectF, cornor, cornor, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); final Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); canvas.drawBitmap(bitmap, src, rect, paint); return output; } catch (Exception e) { return bitmap; } } private int dip2px(Context context, float value) { return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, context.getResources().getDisplayMetrics()) + 0.5f); }}
2.2直接粘代码
public class JoinBitmaps { public static final void join(Canvas canvas, int dimension, List<Bitmap> bitmaps) { if (bitmaps == null) return; int count = Math.min(bitmaps.size(), JoinLayout.max()); float[] size = JoinLayout.size(count); join(canvas, dimension, bitmaps, count, size); } public static final void join(Canvas canvas, int dimension, List<Bitmap> bitmaps, int count, float[] size) { join(canvas, dimension, bitmaps, count, size, 0.15f); } public static final void join(Canvas canvas, int dimension, List<Bitmap> bitmaps, float gapSize) { if (bitmaps == null) return; int count = Math.min(bitmaps.size(), JoinLayout.max()); float[] size = JoinLayout.size(count); join(canvas, dimension, bitmaps, count, size, gapSize); } public static final void join(Canvas canvas, int dimension, List<Bitmap> bitmaps, int count, float[] size, float gapSize) { if (bitmaps == null) return; // 旋转角度 float[] rotation = JoinLayout.rotation(count); // paint Paint paint = new Paint(); paint.setAntiAlias(true); Matrix matrixJoin = new Matrix(); // scale as join size matrixJoin.postScale(size[0], size[0]); canvas.save(); // canvas.drawColor(Color.RED); // index<count bitmaps.size 可能会越界 for (int index = 0; index < count; index++) { Bitmap bitmap = bitmaps.get(index); // MATRIX Matrix matrix = new Matrix(); // scale as destination matrix.postScale((float) dimension / bitmap.getWidth(), (float) dimension / bitmap.getHeight()); canvas.save(); matrix.postConcat(matrixJoin); float[] offset = JoinLayout.offset(count, index, dimension, size); canvas.translate(offset[0], offset[1]); // 缩放 Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); // 裁剪 Bitmap bitmapOk = createMaskBitmap(newBitmap, newBitmap.getWidth(), newBitmap.getHeight(), (int) rotation[index], gapSize); canvas.drawBitmap(bitmapOk, 0, 0, paint); canvas.restore(); } canvas.restore(); } public static final Bitmap createMaskBitmap(Bitmap bitmap, int viewBoxW, int viewBoxH, int rotation, float gapSize) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); final Paint paint = new Paint(); paint.setAntiAlias(true);// 抗锯齿 paint.setFilterBitmap(true); int center = Math.round(viewBoxW / 2f); canvas.drawCircle(center, center, center, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, 0, 0, paint); if (rotation != 360) { Matrix matrix = new Matrix(); // 根据原图的中心位置旋转 matrix.setRotate(rotation, viewBoxW / 2, viewBoxH / 2); canvas.setMatrix(matrix); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawCircle(viewBoxW * (1.5f - gapSize), center, center, paint); } return output; } public static final Bitmap createBitmap(int width, int height, List<Bitmap> bitmaps) { int count = Math.min(bitmaps.size(), JoinLayout.max()); float[] size = JoinLayout.size(count); return createBitmap(width, height, bitmaps, count, size, 0.15f); } public static final Bitmap createBitmap(int width, int height, List<Bitmap> bitmaps, int count, float[] size) { return createBitmap(width, height, bitmaps, count, size, 0.15f); } public static final Bitmap createBitmap(int width, int height, List<Bitmap> bitmaps, int count, float[] size, float gapSize) { Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); int dimen = Math.min(width, height); join(canvas, dimen, bitmaps, count, size, gapSize); return output; }}
2.3直接粘代码
public class JoinLayout { public static final String TAG = JoinLayout.class.getSimpleName(); public static int max() { return 5; } private static final float[][] rotations = { new float[] { 360.0f }, new float[] { 45.0f, 360.0f }, new float[] { 120.0f, 0.0f, -120.0f }, new float[] { 90.0f, 180.0f, -90.0f, 0.0f }, new float[] { 144.0f, 72.0f, 0.0f, -72.0f, -144.0f }, }; public static float[] rotation(int count) { return count > 0 && count <= rotations.length ? rotations[count - 1] : null; } private static final float[][] sizes = { new float[] { 0.9f, 0.9f }, new float[] { 0.5f, 0.65f }, new float[] { 0.45f, 0.8f }, new float[] { 0.45f, 0.91f }, new float[] { 0.38f, 0.80f } }; public static float[] size(int count) { return count > 0 && count <= sizes.length ? sizes[count - 1] : null; } public static float[] offset(int count, int index, float dimension, float[] size) { switch (count) { case 1: return offset1(index, dimension, size); case 2: return offset2(index, dimension, size); case 3: return offset3(index, dimension, size); case 4: return offset4(index, dimension, size); case 5: return offset5(index, dimension, size); default: break; } return new float[] { 0f, 0f }; } /** * 5个头像 * * @param index * 下标 * @param dimension * 画布边长(正方形) * @param size * size[0]缩放 size[1]边距 * @return 下标index X,Y轴坐标 */ private static float[] offset5(int index, float dimension, float[] size) { // 圆的直径 float cd = (float) dimension * size[0]; // 边距 float s1 = -cd * size[1]; float x1 = 0; float y1 = s1; float x2 = (float) (s1 * Math.cos(19 * Math.PI / 180)); float y2 = (float) (s1 * Math.sin(18 * Math.PI / 180)); float x3 = (float) (s1 * Math.cos(54 * Math.PI / 180)); float y3 = (float) (-s1 * Math.sin(54 * Math.PI / 180)); float x4 = (float) (-s1 * Math.cos(54 * Math.PI / 180)); float y4 = (float) (-s1 * Math.sin(54 * Math.PI / 180)); float x5 = (float) (-s1 * Math.cos(19 * Math.PI / 180)); float y5 = (float) (s1 * Math.sin(18 * Math.PI / 180)); // Log.d(TAG, "x1:" + x1 + "/y1:" + y1); // Log.d(TAG, "x2:" + x2 + "/y2:" + y2); // Log.d(TAG, "x3:" + x3 + "/y3:" + y3); // Log.d(TAG, "x4:" + x4 + "/y4:" + y4); // Log.d(TAG, "x5:" + x5 + "/y5:" + y5); // 居中 Y轴偏移量 float xx1 = (dimension - cd - y3 - s1) / 2; // 居中 X轴偏移量 float xxc1 = (dimension - cd) / 2; // xx1 = xxc1 = -s1; // xx1 = xxc1 = 0; switch (index) { case 0: // return new float[] { s1 + xxc1, xx1 }; return new float[] { x1 + xxc1, y1 + xx1 }; case 1: return new float[] { x2 + xxc1, y2 + xx1 }; case 2: return new float[] { x3 + xxc1, y3 + xx1 }; case 3: return new float[] { x4 + xxc1, y4 + xx1 }; case 4: return new float[] { x5 + xxc1, y5 + xx1 }; default: break; } return new float[] { 0f, 0f }; } /** * 4个头像 * * @param index * 下标 * @param dimension * 画布边长(正方形) * @param size * size[0]缩放 size[1]边距 * @return 下标index X,Y轴坐标 */ private static float[] offset4(int index, float dimension, float[] size) { // 圆的直径 float cd = (float) dimension * size[0]; // 边距 float s1 = cd * size[1]; float x1 = 0; float y1 = 0; float x2 = s1; float y2 = y1; float x3 = s1; float y3 = s1; float x4 = x1; float y4 = y3; // Log.d(TAG, "x1:" + x1 + "/y1:" + y1); // Log.d(TAG, "x2:" + x2 + "/y2:" + y2); // Log.d(TAG, "x3:" + x3 + "/y3:" + y3); // Log.d(TAG, "x4:" + x4 + "/y4:" + y4); // 居中 X轴偏移量 float xx1 = (dimension - cd - s1) / 2; switch (index) { case 0: return new float[] { x1 + xx1, y1 + xx1 }; case 1: return new float[] { x2 + xx1, y2 + xx1 }; case 2: return new float[] { x3 + xx1, y3 + xx1 }; case 3: return new float[] { x4 + xx1, y4 + xx1 }; default: break; } return new float[] { 0f, 0f }; } /** * 3个头像 * * @param index * 下标 * @param dimension * 画布边长(正方形) * @param size * size[0]缩放 size[1]边距 * @return 下标index X,Y轴坐标 */ private static float[] offset3(int index, float dimension, float[] size) { // 圆的直径 float cd = (float) dimension * size[0]; // 边距 float s1 = cd * size[1]; // 第二个圆的 Y坐标 float y2 = s1 * (3 / 2); // 第二个圆的 X坐标 float x2 = s1 - y2 / 1.73205f; // 第三个圆的 X坐标 float x3 = s1 * 2 - x2; // 居中 Y轴偏移量 float xx1 = (dimension - cd - y2) / 2; // 居中 X轴偏移量 float xxc1 = (dimension - cd) / 2 - s1; // xx1 = xxc1 = 0; switch (index) { case 0: return new float[] { s1 + xxc1, xx1 }; case 1: return new float[] { x2 + xxc1, y2 + xx1 }; case 2: return new float[] { x3 + xxc1, y2 + xx1 }; default: break; } return new float[] { 0f, 0f }; } /** * 2个头像 * * @param index * 下标 * @param dimension * 画布边长(正方形) * @param size * size[0]缩放 size[1]边距 * @return 下标index X,Y轴坐标 */ private static float[] offset2(int index, float dimension, float[] size) { // 圆的直径 float cd = (float) dimension * size[0]; // 边距 float s1 = cd * size[1]; float x1 = 0; float y1 = 0; float x2 = s1; float y2 = s1; // Log.d(TAG, "x1:" + x1 + "/y1:" + y1); // Log.d(TAG, "x2:" + x2 + "/y2:" + y2); // 居中 X轴偏移量 float xx1 = (dimension - cd - s1) / 2; switch (index) { case 0: return new float[] { x1 + xx1, y1 + xx1 }; case 1: return new float[] { x2 + xx1, y2 + xx1 }; default: break; } return new float[] { 0f, 0f }; } /** * 1个头像 * * @param index * 下标 * @param dimension * 画布边长(正方形) * @param size * size[0]缩放 size[1]边距 * @return 下标index X,Y轴坐标 */ private static float[] offset1(int index, float dimension, float[] size) { // 圆的直径 float cd = (float) dimension * size[0]; float offset = (dimension - cd) / 2; return new float[] { offset, offset }; }}
2.4在MainActivity中
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Resources r = getResources(); Bitmap b1 = BitmapFactory.decodeResource(r,R.drawable.a1); Bitmap b2 = BitmapFactory.decodeResource(r,R.drawable.a2); Bitmap b3 = BitmapFactory.decodeResource(r,R.drawable.a3); Bitmap [] bitmaps={b1,b2,b3,b1,b2,b3,b1,b2,b3}; GroupView gridView= (GroupView) findViewById(R.id.group_view); gridView.setImageBitmaps(bitmaps); }
2.5在布局中
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:tgBtn="http://schemas.android.com/apk/res-auto" tools:context="com.bitmap.activity.MainActivity"> <com.bitmap.activity.GroupView //引用自己包下的GroupView android:id="@+id/group_view" android:layout_width="100dp" android:layout_height="100dp" xmlns:app="http://schemas.android.com/apk/res-auto" app:type="circle" app:padding="3dp" app:cornor="10dp" app:backgroundGP="#ff99"/></RelativeLayout>
这里通过自定义属性设置:
type:圆或者方
padding:图片间距
cornor:设置圆角矩形
backgroundGp:背景颜色
这就是所有的代码!!!
阅读全文
0 0
- Android学习之仿QQ讨论组和微信群聊头像
- Android学习之仿QQ讨论组和微信群聊头像
- Android仿QQ圆形头像
- Android实战之 上传头像 和仿QQ空间、微博发表文字和图片
- android自定义View 之仿QQ消息头像
- Android:高仿QQ头像截取
- Android 仿qq上传头像(一)
- Android 仿QQ讨论组头像
- 仿QQ头像截取
- Android:高仿QQ头像截取升级版
- 高仿QQ头像截取
- 高仿QQ头像截取
- 仿QQ头像裁剪功能
- 仿qq用户头像上传
- android学习笔记之 Fragment使用 仿QQ
- Android学习之仿QQ侧滑功能的实现
- Android学习之仿QQ聊天界面的实现
- Android学习笔记之 仿QQ登录界面的实现
- 安装 和使用 armadillo
- 【Protocol Buffer】Protobuf的序列化和反序列化
- Centos 6.9 Install nodejs 6
- 文章标题
- java学习之路(5)-运算符
- Android学习之仿QQ讨论组和微信群聊头像
- Codeforces Round #423Div. 2 A-E题解
- 《加密与解密》笔记五(二)
- struts2多文件上传
- Singleton单例模式
- 利用风骚小递归遍历MenuStrip获取TreeView中的TreeNode项
- @Basic
- Java系列
- Java 8 流式处理提高程序响应