首页 » 技术分享 » 高仿QQ讨论组头像拼图

高仿QQ讨论组头像拼图

 

讨论组如果没有头像,体验较差,我们会选择讨论组成员来拼成一个新图,最多五张。先贴上自定义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了,布局文件自己写吧,懒得写了。



转载自原文链接, 如需删除请联系管理员。

原文链接:高仿QQ讨论组头像拼图,转载请注明来源!

0