依然是针对Launcher2的代码解析,并且是关于创建的快捷方式图标的一点代码解析和后期处理方式。
直接看代码,Utilities.java,因为快捷方式图标绘制最后返回的bitmap对象是在这个类中完成的,在之前的博客也提到过可以给应用图标添加统一的背景图,同样的在这个类中实际也是可以实现的。
直接上代码,其中增加了添加统一背景的代码,可以结合之前的文章参考来做,效果是一样的。
这次主要来解析下下面这个函数的过程
/** * Returns a bitmap suitable for the all apps view. */ static Bitmap createIconBitmap(Drawable icon, Context context) { synchronized (sCanvas) { // we share the statics :-( if (sIconWidth == -1) { initStatics(context); } //将icon的默认宽和高赋值给width和height,sIconWidth,sIconHeight的定义可以在代码中找到 int width = sIconWidth; int height = sIconHeight; if (icon instanceof PaintDrawable) { PaintDrawable painter = (PaintDrawable) icon; painter.setIntrinsicWidth(width); painter.setIntrinsicHeight(height); } else if (icon instanceof BitmapDrawable) { // Ensure the bitmap has a density. //直接从Drawable中获取bitmap对象 BitmapDrawable bitmapDrawable = (BitmapDrawable) icon; Bitmap bitmap = bitmapDrawable.getBitmap(); BitmapDrawable bitmapDrawable = (BitmapDrawable) icon; Bitmap bitmap = bitmapDrawable.getBitmap(); //设置icon的适配DPI参数,可忽略 if (bitmap.getDensity() == Bitmap.DENSITY_NONE) { bitmapDrawable.setTargetDensity(context.getResources() .getDisplayMetrics()); } } //获取适配的应用图标实际大小,正常情况下会有三个尺寸48*48,72*72,96*96 int sourceWidth = icon.getIntrinsicWidth(); int sourceHeight = icon.getIntrinsicHeight(); if (sourceWidth > 0 && sourceHeight > 0) { // There are intrinsic sizes. if (width < sourceWidth || height < sourceHeight) { // It's too big, scale it down. //应用图标尺寸大于默认尺寸,则默认尺寸按比例缩放至应用图标的宽高比例 final float ratio = (float) sourceWidth / sourceHeight; if (sourceWidth > sourceHeight) { height = (int) (width / ratio); } else if (sourceHeight > sourceWidth) { width = (int) (height * ratio); } } else if (sourceWidth < width && sourceHeight < height) { // Don't scale up the icon //应用图标大小小于默认给定大小,不进行裁剪缩放 width = sourceWidth; height = sourceHeight; } } //默认icon图标大小 // no intrinsic size --> use default size int textureWidth = sIconTextureWidth; int textureHeight = sIconTextureHeight; //创建画布为默认icon大小 final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight, Bitmap.Config.ARGB_8888); final Canvas canvas = sCanvas; canvas.setBitmap(bitmap); final int left = (textureWidth - width) / 2; final int top = (textureHeight - height) / 2; @SuppressWarnings("all") // suppress dead code warning final boolean debug = false; if (debug) { // draw a big box for the icon for debugging canvas.drawColor(sColors[sColorIndex]); if (++sColorIndex >= sColors.length) sColorIndex = 0; Paint debugPaint = new Paint(); debugPaint.setColor(0xffcccc00); canvas.drawRect(left, top, left + width, top + height, debugPaint); } /** * 添加统一背景,另一种方案,简单说就是利用一个现有的bitmap创建一个画布,并将图标画在这个画布上,实现增加背景的功能투ᅪ뾰ᄏᄆᄈᄒᄚ */ /* if (true) { Bitmap backBitmap = BitmapFactory.decodeResource( context.getResources(), R.drawable.icon_bg); int backWidth = backBitmap.getWidth(); int backHeight = backBitmap.getHeight(); if (backWidth != sIconWidth || backHeight != sIconHeight) { Matrix matrix = new Matrix(); matrix.postScale((float) sIconWidth / backWidth, (float) sIconHeight / backHeight); canvas.drawBitmap(Bitmap.createBitmap(backBitmap, 0, 0, backWidth, backHeight, matrix, true), 0.0f, 0.0f, null); } else { canvas.drawBitmap(backBitmap, 0.0f, 0.0f, null); } }*/ 将应用图标bitmap绘制在画布上 sOldBounds.set(icon.getBounds()); icon.setBounds(left, top, left + width, top + height); icon.draw(canvas); icon.setBounds(sOldBounds); canvas.setBitmap(null); //返回已经过处理的圆角bitmap return getRoundedBitmap(bitmap); } }
//bitmap圆角处理 public static Bitmap getRoundedBitmap(Bitmap mBitmap){ //Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.frame); //创建与原始位图大小相同的画布位图ᄡᄡᄑ따샤ᅫ콰ᄐ Bitmap bgBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Config.ARGB_8888); //初始化画布 Canvas mCanvas = new Canvas(bgBitmap); Paint mPaint = new Paint(); Rect mRect = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight()); RectF mRectF = new RectF(mRect); //设置圆角半径 float roundPx = 70; mPaint.setAntiAlias(true); //绘制圆角矩形 mCanvas.drawRoundRect(mRectF, roundPx, roundPx, mPaint); //设置图像的叠加模式, 此处模式选择可参考后面的规则 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); //绘制图像 mCanvas.drawBitmap(mBitmap, mRect, mRect, mPaint); return bgBitmap; }
通过以上的代码就可以实现应用图标的圆角处理,效果可在修改后自行看到,在此不贴图了,每次截图甚是麻烦。同时对于位图的处理实际还可以有很多做法,可以参考来做,诸多效果在此借鉴下其他网友的做法
带倒影的图标位图处理代码
public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) { final int reflectionGap = 4; int w = bitmap.getWidth(); int h = bitmap.getHeight(); Matrix matrix = new Matrix(); matrix.preScale(1, -1); Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, h / 2, w, h / 2, matrix, false); Bitmap bitmapWithReflection = Bitmap.createBitmap(w, (h + h / 2), Config.ARGB_8888); Canvas canvas = new Canvas(bitmapWithReflection); canvas.drawBitmap(bitmap, 0, 0, null); Paint deafalutPaint = new Paint(); canvas.drawRect(0, h, w, h + reflectionGap, deafalutPaint); canvas.drawBitmap(reflectionImage, 0, h + reflectionGap, null); Paint paint = new Paint(); LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP); paint.setShader(shader); // Set the Transfer mode to be porter duff and destination in paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); // Draw a rectangle using the paint with our linear gradient canvas.drawRect(0, h, w, bitmapWithReflection.getHeight() + reflectionGap, paint); return bitmapWithReflection; }还有直接可以缩放drawable对象的代码,这样可以不用刻意的获取drawable的bitmap对象位图再对位图进行缩放,再绘制去实现缩放的功能。
public static Drawable zoomDrawable(Drawable drawable, int w, int h) { int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); // drawable转换成bitmap Bitmap oldbmp = drawableToBitmap(drawable); // 创建操作图片用的Matrix对象 Matrix matrix = new Matrix(); // 计算缩放比例 float sx = ((float) w / width); float sy = ((float) h / height); // 设置缩放比例 matrix.postScale(sx, sy); // 建立新的bitmap,其内容是对原bitmap的缩放后的图 Bitmap newbmp = Bitmap.createBitmap(oldbmp, 0, 0, width, height, matrix, true); return new BitmapDrawable(newbmp); }
bitmap的缩放处理代码
public static Bitmap zoomBitmap(Bitmap bitmap, int width, int height) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); Matrix matrix = new Matrix(); float scaleWidth = ((float) width / w); float scaleHeight = ((float) height / h); matrix.postScale(scaleWidth, scaleHeight); Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true); return newbmp; }
以上就是对于launcher2的图标处理方法的解析和修改。