高仿QQ讨论组头像拼图
来源:互联网 发布:黑帽seo 编辑:程序博客网 时间:2024/04/30 21:45
讨论组如果没有头像,体验较差,我们会选择讨论组成员来拼成一个新图,最多五张。先贴上自定义View CircularImageView核心代码:
public class CircularImageView extends View { protected int viewWidth; protected int viewHeight; protected ArrayList<Bitmap> bmps; public CircularImageView(Context context) { super(context); } public CircularImageView(Context context, AttributeSet attrs) { super(context, attrs); } public CircularImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); int dimen = Math.min(width, height); setMeasuredDimension(dimen, dimen); } public void setImageBitmaps(ArrayList<Bitmap> bitmaps) { if (bitmaps == null) throw new IllegalArgumentException("bitmaps can not be Null"); if (bitmaps.size() > JoinLayout.max()) throw new IllegalArgumentException("bitmaps size can not be greater than " + JoinLayout.max()); this.bmps = bitmaps; invalidate(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); viewWidth = w; viewHeight = h; viewWidth = viewHeight = Math.min(w, h); } @Override public void onDraw(Canvas canvas) { if (viewWidth > 0 && viewHeight > 0) { JoinBitmaps.join(canvas, viewWidth, bmps, 0.15f); } }}这个View 主要要塞入一组比Bitmap ,然后重绘。这里用到了JoinBitmaps 这类,代买如下:
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); for (int index = 0; index < bitmaps.size(); 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; }}
和JoinLayout这类,代码如下:
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 }, new float[] { 45, 360 }, new float[] { 120, 0, -120 }, new float[] { 90, 180, -90, 0 }, new float[] { 144, 72, 0, -72, -144 }, }; 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 width * 画布边长(正方形�? * @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 width * 画布边长(正方形�? * @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 width * 画布边长(正方形�? * @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 width * 画布边长(正方形�? * @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 width * 画布边长(正方形�? * @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 }; }}核心代码已经贴出来了,剩下就是界面,Activity,adapter ,Item ,我一起给,如下:
public class Item {private String name;private String age;public ArrayList<Bitmap> bitmapList ;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}Item(String name, String age , ArrayList<Bitmap> bitmapList) {this.name = name;this.age = age;this.bitmapList = bitmapList ;}}
public class ItemAdapter extends BaseAdapter{private List<Item> itemList = new ArrayList<Item>();private LayoutInflater inflater;private ArrayList<Bitmap> GroupHeaderText = new ArrayList<Bitmap>();private Bitmap imgBitmap = null ;public ItemAdapter(Context c,List<Item> itemList) {// TODO Auto-generated constructor stubinflater = LayoutInflater.from(c);this.itemList = itemList ; imgBitmap = BitmapFactory.decodeResource(c.getResources(), R.drawable.header); GroupHeaderText.add(imgBitmap);}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn itemList.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic long getItemId(int arg0) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubViewHolder holder;if (convertView == null) {holder = new ViewHolder();convertView = inflater.inflate(R.layout.item, null);holder.name = (TextView) convertView.findViewById(R.id.id_treenode_label);holder.age = (TextView) convertView.findViewById(R.id.id_treenode_online);holder.mImageView1 = (CircularImageView) convertView.findViewById(R.id.circularImageView);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}holder.name.setSelected(true);holder.name.setText(itemList.get(position).getName());if(!TextUtils.isEmpty(itemList.get(position).getAge())){holder.age.setVisibility(View.VISIBLE);holder.age.setText(itemList.get(position).getAge());}else{holder.age.setVisibility(View.GONE);}if(itemList.get(position).bitmapList != null){holder.mImageView1.setImageBitmaps(itemList.get(position).bitmapList);}else{holder.mImageView1.setImageBitmaps(GroupHeaderText);}return convertView;}class ViewHolder {CircularImageView mImageView1;TextView name;// TextView department;TextView age;TextView header;// View divider;}}
public class MainActivity extends ActionBarActivity {private List<Item> itemList = new ArrayList<Item>();private ListView list;private ItemAdapter itemAdapter;private Bitmap imgBitmap;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initId();initData();itemAdapter = new ItemAdapter(getApplicationContext(), itemList);list.setAdapter(itemAdapter);}public void initId() {list = (ListView) findViewById(R.id.list);imgBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.header);}public void initData() {ArrayList<Bitmap> bitmap = new ArrayList<Bitmap>();bitmap.add(imgBitmap);bitmap.add(imgBitmap);itemList.add(new Item("A", "1", bitmap));ArrayList<Bitmap> bitmap2 = new ArrayList<Bitmap>();bitmap2.add(imgBitmap);bitmap2.add(imgBitmap);bitmap2.add(imgBitmap);itemList.add(new Item("A", "1", bitmap2));ArrayList<Bitmap> bitmap3 = new ArrayList<Bitmap>();bitmap3.add(imgBitmap);bitmap3.add(imgBitmap);bitmap3.add(imgBitmap);itemList.add(new Item("A", "1", bitmap3));ArrayList<Bitmap> bitmap4 = new ArrayList<Bitmap>();bitmap4.add(imgBitmap);bitmap4.add(imgBitmap);bitmap4.add(imgBitmap);bitmap4.add(imgBitmap);itemList.add(new Item("A", "1", bitmap4));ArrayList<Bitmap> bitmap5 = new ArrayList<Bitmap>();bitmap5.add(imgBitmap);bitmap5.add(imgBitmap);bitmap5.add(imgBitmap);bitmap5.add(imgBitmap);bitmap5.add(imgBitmap);itemList.add(new Item("A", "1", bitmap5));itemList.add(new Item("A", "1", null));itemList.add(new Item("AKJfhakdjfklas;jfklasdfjalskjfsdakfjlkasjdjfk;asdjfkasdjf","1", null));itemList.add(new Item("A", "1", null));}}ok了,布局文件自己写吧,懒得写了。
0 0
- 高仿QQ讨论组头像拼图
- Android 仿QQ讨论组头像
- android 群组头像的显示(仿QQ群组)
- android 群组头像的显示(仿QQ群组)
- Swift - QQ讨论组头像的实现 (多人聊天的组合头像)
- 关于QQ群头像以及微信讨论组头像的工具类
- 高仿qq健康
- 群组头像拼接
- 高仿QQ(登录界面)
- 高仿QQ(聊天窗口)
- 高仿QQ(主界面)
- 高仿qq聊天界面
- 高仿QQ头像截取
- 高仿QQ头像截取
- 高仿QQ界面(2)
- 高仿腾讯QQ最终版
- 【win32】高仿QQ截图
- 高仿QQ主界面
- Clsaa.forName(xxx.xxx.xx);
- CentOS 上 Jenkins 安装
- Machine Learning - Andrew Ng on Coursera (Week 5)
- viewpager内嵌listview或者girdview无法滑动问题。
- 图片压缩
- 高仿QQ讨论组头像拼图
- 【bzoj2242】[SDOI2011]计算器 快速幂+BSGS
- 广告轮播
- Machine Learning - Andrew Ng on Coursera (Week 6)
- [BZOJ2938][POI2000]病毒 做题笔记
- Linux性能监测:磁盘IO
- Kubernetes1.2新特性分析(二)
- 关于数组的逆置问题
- 正则表达式的优先级