讨论组如果没有头像,体验较差,我们会选择讨论组成员来拼成一个新图,最多五张。先贴上自定义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 stub
inflater = LayoutInflater.from(c);
this.itemList = itemList ;
imgBitmap = BitmapFactory.decodeResource(c.getResources(), R.drawable.header);
GroupHeaderText.add(imgBitmap);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return itemList.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder 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;
@Override
protected 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了,布局文件自己写吧,懒得写了。