Android的Drawable圆角矩形处理

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);
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值