上图
逻辑
当图片是2张时,整张图片是2*2的 正方形,第1.2张占满第1.5行
当图片是3张时,整张图片是2*2的 正方形,第1.2张占满第一行,第三张图片第二行居中
当图片是4张时,整张图片是2*2的 正方形
当图片是5张时,整张图片是3*3的 正方形,第1.2.3张占满第1.5行,第4.5 张图片第2.5行居中
当图片是6张时,整张图片是3*3的 正方形,第1.2.3张占满第1.5行,第4.5.6 张图片占满第2.5行
当图片是7张时,整张图片是3*3的 正方形,第1.2.3张占满第1行,第4.5.6 张图片占满第2行,第7张第3行居中
当图片是7张时,整张图片是3*3的 正方形,第1.2.3张占满第1行,第4.5.6 张图片占满第2行,第7.8张第3行居中
当图片是9张时,整张图片是3*3的 正方形
上代码
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Environment;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import android.graphics.Paint;
public class GroupIconGenerator {
private OkHttpClient client = new OkHttpClient();
public void createGroupIcon(final Context context, List<String> imageUrls, final GroupIconCallback callback) {
if(imageUrls.size()>9){
imageUrls= imageUrls.subList(0,8);
}
final CountDownLatch latch = new CountDownLatch(imageUrls.size());
final List<Bitmap> bitmaps = new ArrayList<>();
for (String url : imageUrls) {
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
latch.countDown();
// Handle failure
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
InputStream inputStream = response.body().byteStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
synchronized (bitmaps) {
bitmaps.add(bitmap);
}
}
latch.countDown();
}
});
}
new Thread(() -> {
try {
latch.await(); // Wait for all downloads to complete
Bitmap groupIcon = combineImagesToGrid(bitmaps); // Combine images to grid
String filePath = saveBitmapToFile(context, groupIcon); // Save bitmap to file
callback.onGroupIconGenerated(filePath); // Callback with file path
} catch (InterruptedException | IOException e) {
callback.onError(e); // Handle errors
}
}).start();
}
public Bitmap combineImagesToGrid(List<Bitmap> images) {
if (images == null || images.isEmpty()) {
throw new IllegalArgumentException("Image list must not be null or empty");
}
int imageCount = images.size();
if (imageCount > 9 || imageCount < 2) {
throw new IllegalArgumentException("Image count should be between 2 and 9");
}
// 设置每张图的最大尺寸
int maxImageSize = 640; // 这个值可以根据需要调整
int gridSpacing = 10; // 网格间的间距
// 根据图片数量计算网格的宽高
int rows, cols, gridWidth, gridHeight;
if (imageCount <= 4) {
rows = cols = 2;
} else {
rows = cols = 3;
}
gridWidth = cols * maxImageSize + (cols - 1) * gridSpacing;
gridHeight = rows * maxImageSize + (rows - 1) * gridSpacing;
// 创建一个大的Bitmap作为底图
Bitmap result = Bitmap.createBitmap(gridWidth, gridHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
// 绘制半透明黑色背景
int backgroundColor = Color.WHITE;
canvas.drawColor(backgroundColor);
int left, top;
for (int i = 0; i < images.size(); i++) {
int colNum = i % cols; // 计算列位置
int rowNum = i / cols; // 计算行位置
// 根据不同的图片数量和索引计算left和top的值
if (imageCount == 2) {
left = colNum * (maxImageSize + gridSpacing);
top = (gridHeight - maxImageSize) / 2; // 居中
} else if (imageCount == 3 && i == 2) {
left = (gridWidth - maxImageSize) / 2; // 居中
top = maxImageSize + gridSpacing;
} else if (imageCount == 5 ) {
if (i < 3) {
// 前三张图片(第一行)
left = colNum * (maxImageSize + gridSpacing);
top = (gridHeight - 2 * maxImageSize - gridSpacing) / 2; // 垂直居中的起始位置
} else {
// 后两张图片(第二行)
left = ((gridWidth - 2 * maxImageSize - gridSpacing) / 2) + (i - 3) * (maxImageSize + gridSpacing);
top = ((gridHeight - 2 * maxImageSize - gridSpacing) / 2) + maxImageSize + gridSpacing; // 垂直居中的第二行位置
}
} else if (imageCount == 6) {
left = colNum * (maxImageSize + gridSpacing);
if (i < 3) {
// 前三张图片(第一行)
top = (gridHeight - 2 * maxImageSize - gridSpacing) / 2; // 垂直居中的起始位置
} else {
// 后三张图片(第二行)
top = ((gridHeight - 2 * maxImageSize - gridSpacing) / 2) + maxImageSize + gridSpacing; // 垂直居中的第二行位置
}
} else if (imageCount == 7 && i == 6) {
left = (gridWidth - maxImageSize) / 2; // 居中
top = 2 * (maxImageSize + gridSpacing);
} else if (imageCount == 8 && i >= 6) {
left = ((gridWidth - 2 * maxImageSize - gridSpacing) / 2) + (i - 6) * (maxImageSize + gridSpacing);
top = 2 * (maxImageSize + gridSpacing);
} else {
left = colNum * (maxImageSize + gridSpacing);
top = rowNum * (maxImageSize + gridSpacing);
}
// 缩放Bitmap
Bitmap scaledBitmap = Bitmap.createScaledBitmap(images.get(i), maxImageSize, maxImageSize, true);
// 将图片绘制到Canvas上
canvas.drawBitmap(scaledBitmap, left, top, paint);
// 如果你不再需要这个缩放后的bitmap, 请确保它被回收
if (scaledBitmap != images.get(i)) {
scaledBitmap.recycle();
}
}
return result;
}
private String saveBitmapToFile(Context context, Bitmap bitmap) throws IOException {
String fileName = "group_icon_" + System.currentTimeMillis() + ".png";
File directory = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File file = new File(directory, fileName);
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
return file.getAbsolutePath();
}
public interface GroupIconCallback {
void onGroupIconGenerated(String filePath);
void onError(Exception e);
}
}