package com.example.demo;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
//import android.support.v4.content.res.ResourcesCompat;
import androidx.core.content.res.ResourcesCompat;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
public class MainActivity extends FlutterActivity {
// 一个应用中所使用的所有通道名称必须是唯一的。
private static final String CHANNEL = "samples.flutter.dev/example";
private static final String PKG_NAME = "com.example.demo";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
// Note: this method is invoked on the main thread.
if (call.method.equals("getAppIcon")) {
Drawable appIcon = getAppIcon(PKG_NAME + ".MainActivity");
if (appIcon != null) {
appIcon = decorateAppIcon(appIcon, call.arguments);
result.success(drawableToBytes(appIcon));
} else {
result.success(null);
}
} else {
logToConsole(call.method, "notImplemented");
result.notImplemented();
}
}
);
}
/**
* @param activityName 目标活动名。
* @return
*/
private Drawable getAppIcon(String activityName) {
/** return ResourcesCompat.getDrawable(getResources(), R.drawable.ic_launcher, null); */
PackageManager pm = getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
for (ResolveInfo info : resolveInfos) {
ActivityInfo activityInfo = info.activityInfo;
// logToConsole("getAppIcon", activityInfo.name);
if (activityName.equals(activityInfo.name)) {
Drawable icon = activityInfo.loadIcon(pm);
return icon;
}
}
return null;
}
private Drawable decorateAppIcon(Drawable appIcon, Object callArguments) {
/** 重新赋值给appIcon 是为了使用更好的图片进行编码调试 */
// appIcon = ResourcesCompat.getDrawable(getResources(), R.drawable.icon_edp, null);
float sizeW = 0;
float sizeH = 0;
int cornerRadius = -1;
if (callArguments != null && (callArguments instanceof Map)) {
Map tempMap = (Map) callArguments;
Object tempValue = tempMap.get("sizeW");
if (tempValue instanceof Double) {
sizeW = ((Double) tempValue).floatValue();
}
tempValue = tempMap.get("sizeH");
if (tempValue instanceof Double) {
sizeH = ((Double) tempValue).floatValue();
}
tempValue = tempMap.get("cornerRadius");
if (tempValue instanceof Double) {
cornerRadius = ((Double) tempValue).intValue();
}
}
// 若取值不合理, 则按默认处理。
if (sizeW <= 0) {
sizeW = 72;
}
if (sizeH <= 0) {
sizeH = 72;
}
if (cornerRadius < 0) {
cornerRadius = 18;
}
int maxCornerRadius = (int) (Math.min(sizeW, sizeH) / 2);
if (cornerRadius > maxCornerRadius) {
cornerRadius = maxCornerRadius;
}
final int originDrawableW = appIcon.getIntrinsicWidth();
final int originDrawableH = appIcon.getIntrinsicHeight();
float actualSizeW;
float actualSizeH;
int actualCornerRadius;
// 此处的处理规则: BoxFit.cover ( 充满容器, 保持图片的宽高比, 可能会被截断 ) 。
if (originDrawableW / sizeW <= originDrawableH / sizeH) {
actualSizeW = originDrawableW;
actualSizeH = sizeH * originDrawableW / sizeW;
actualCornerRadius = (int) (cornerRadius * originDrawableW / sizeW);
} else {
actualSizeH = originDrawableH;
actualSizeW = sizeW * originDrawableH / sizeH;
actualCornerRadius = (int) (cornerRadius * originDrawableH / sizeH);
}
final int finalSizeW = (int) actualSizeW;
final int finalSizeH = (int) actualSizeH;
final int finalCornerRadius = actualCornerRadius;
// logToConsole("decorateAppIcon_orgin", originDrawableW + "_" + originDrawableH);
// logToConsole("decorateAppIcon_actual", actualSizeW + "_" + actualSizeH);
Bitmap bitmap = drawableToBitmap(appIcon, finalSizeW, finalSizeH);
if (0 == finalCornerRadius) {
// logToConsole("decorateAppIcon", "returnDirectly");
return new BitmapDrawable(bitmap);
}
// logToConsole("decorateAppIcon", "aboutToDrawableWithCornerRadius");
return drawableWithCornerRadius(bitmap, finalCornerRadius);
}
private Drawable drawableWithCornerRadius(final Bitmap bitmap, final int cornerRadius) {
final int finalSizeW = bitmap.getWidth();
final int finalSizeH = bitmap.getHeight();
final Paint paint = new Paint();
paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
paint.setAntiAlias(true);
paint.setDither(true);
return new Drawable() {
public void draw(Canvas canvas) {
// 对整个画布染色。
//canvas.drawColor(Color.BLUE);
canvas.drawColor(0xf3f3f3);
final int rectLeft = 0;
final int rectTop = 0;
final Rect rect = new Rect(rectLeft, rectTop,
rectLeft + bitmap.getWidth(), rectTop + bitmap.getHeight());
// logToConsole("drawableWithCornerRadius", rect.toString());
canvas.drawRoundRect(new RectF(rect), cornerRadius, cornerRadius, paint);
}
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
public void setColorFilter(ColorFilter colorFilter) {
paint.setColorFilter(colorFilter);
}
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
public int getIntrinsicWidth() {
return finalSizeW;
}
public int getIntrinsicHeight() {
return finalSizeH;
}
};
}
/**
* @param expectW 期望宽度 ( 若传0则表示使用原图宽度 ) 。
* @param expectH 期望高度 ( 若传0则表示使用原图高度 ) 。
* @note 超出部分会被裁剪。
*/
private Bitmap drawableToBitmap(Drawable drawable, int expectW, int expectH) {
// 声明将要创建的bitmap 。
Bitmap bitmap;
// 获取图片宽高。
final int originW = drawable.getIntrinsicWidth();
final int originH = drawable.getIntrinsicHeight();
if (drawable instanceof BitmapDrawable &&
((0 == expectW && 0 == expectH) || (originW == expectW && originH == expectH))) {
// logToConsole("drawableToBitmap", "returnDirectly");
return ((BitmapDrawable) drawable).getBitmap();
}
final int w = (0 == expectW ? originW : Math.min(originW, expectW));
final int h = (0 == expectH ? originH : Math.min(originH, expectH));
final int boundLeft = (w - originW) / 2;
final int boundTop = (h - originH) / 2;
final Rect bounds = new Rect(boundLeft, boundTop, (boundLeft + originW), (boundTop + originH));
// logToConsole("drawableToBitmap", bounds.toString());
// 图片位深, PixelFormat.OPAQUE代表没有透明度, RGB_565就是没有透明度的位深, 否则就用ARGB_8888 。
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ?
Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
// 创建一个空的Bitmap 。
bitmap = Bitmap.createBitmap(w, h, config);
// 在bitmap上创建一个画布。
Canvas canvas = new Canvas(bitmap);
// 设置drawable在画布上的位置。
drawable.setBounds(bounds);
// 将drawable绘制到画布上。
drawable.draw(canvas);
return bitmap;
}
private byte[] drawableToBytes(Drawable drawable) {
Bitmap bitmap = drawableToBitmap(drawable, 0, 0);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
}
private void logToConsole(String tagSuffix, String msg) {
// Log.d("MainActivity_" + tagSuffix, msg);
}
}
Android的Drawable圆角矩形处理
于 2023-03-15 09:22:53 首次发布