一、View转换为Bitmap
在Android中所有的控件都是View的直接子类或者间接子类,经由过程它们可以组成丰硕的UI界面。在视窗显示的时辰Android会把这些控件都加载到RAM中,形成一个以ViewRoot为根节点的控件树,然后由根节点起头逐级把控件绘制到屏幕上。
可以经由过程挪用控件的setDrawingCacheEnabled(true)体例,开启绘图缓存功能,在绘制View的时辰把图像缓存起来,然后经由过程getDrawingCache()体例获取这个缓存的Bitmap。需要注重的是,当不再使用这个Bitmap时,需要挪用destroyDrawingCache()体例,释放Bitmap资本。因为在绘制View到屏幕时缓存图像会降低控件绘制的效率,是以只会在需要使用View的图像缓存的时辰才挪用setDrawingCacheEnabled(true)体例开启图像缓存功能,当不再使用图像缓存时需要挪用setDrawingCacheEnabled(false) 封锁图像缓存功能。
这种体例在撑持拖拽类型的应用中经常见到,在Android系统的Launcher应用中也使用了这种体例,当用户拖拽应用的快捷图标时,获取到控件对应的Bitmap,然后操作这个Bitmap跟着手指移动。
下面经由过程一段轨范代码来声名若何获取View对应的Bitmap。在轨范代码中使用了两个ImageView并给它们都设置了显示的图像资本,然后把第一个ImageView对应的bitmap显示到第二个ImageView中。因为在Activity的onCreate体例中挪用这个体例,当执行Activity的onCreate体例时,控件还没有筹备好,所以需要使用Handler进行延迟操作,Java轨范代码如下文所示:
// View转换为Bitmap void getDrawingCache(final ImageView sourceImageView, final ImageView destImageView) { new Handler().postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub // 开启bitmap缓存 sourceImageView.setDrawingCacheEnabled(true); // 获取bitmap缓存 Bitmap mBitmap = sourceImageView.getDrawingCache(); // 显示 bitmap destImageView.setImageBitmap(mBitmap); // Bitmap mBitmap = sourceImageView.getDrawingCache(); // Drawable drawable = (Drawable) new BitmapDrawable(mBitmap); // destImageView.setImageDrawable(drawable); new Handler().postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub // 不再显示bitmap缓存 // destImageView.setImageBitmap(null); destImageView.setImageResource(R.drawable.anims); // 使用这句话而不是用上一句话是错误的,空指针挪用 // destImageView.setBackgroundDrawable(null); // 封锁bitmap缓存 sourceImageView.setDrawingCacheEnabled(false); // 释放bitmap缓存资本 sourceImageView.destroyDrawingCache(); } }, DELAY_TIME); } }, DELAY_TIME); }
运行下场如下文所示:
图7-3 Demo运行下场图1
图7-4 Demo运行下场图2
public Bitmap getRoundedBitmap() { Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.default_1); // 建树新的位图 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); // 设置圆角半径为20 float roundPx = 15; 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; }
图7-5 图像圆角措置
// 图像灰化措置 public Bitmap getGrayBitmap() { Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.anims); Bitmap mGrayBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Config.ARGB_8888); Canvas mCanvas = new Canvas(mGrayBitmap); Paint mPaint = new Paint(); // 建树颜色变换矩阵 ColorMatrix mColorMatrix = new ColorMatrix(); // 设置灰度影响规模 mColorMatrix.setSaturation(0); // 建树颜色过滤矩阵 ColorMatrixColorFilter mColorFilter = new ColorMatrixColorFilter( mColorMatrix); // 设置画笔的颜色过滤矩阵 mPaint.setColorFilter(mColorFilter); // 使用措置后的画笔绘制图像 mCanvas.drawBitmap(mBitmap, 0, 0, mPaint); return mGrayBitmap; }
图7-6 图像灰化措置
// 提取图像Alpha位图 public Bitmap getAlphaBitmap() { BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources() .getDrawable(R.drawable.anims); Bitmap mBitmap = mBitmapDrawable.getBitmap(); // BitmapDrawable的getIntrinsicWidth()体例,Bitmap的getWidth()体例 // 注重这两个体例的区别 // Bitmap mAlphaBitmap = // Bitmap.createBitmap(mBitmapDrawable.getIntrinsicWidth(), // mBitmapDrawable.getIntrinsicHeight(), Config.ARGB_8888); Bitmap mAlphaBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Config.ARGB_8888); Canvas mCanvas = new Canvas(mAlphaBitmap); Paint mPaint = new Paint(); mPaint.setColor(Color.BLUE); // 从原位图中提取只包含alpha的位图 Bitmap alphaBitmap = mBitmap.extractAlpha(); // 在画布上(mAlphaBitmap)绘制alpha位图 mCanvas.drawBitmap(alphaBitmap, 0, 0, mPaint); return mAlphaBitmap; }
图7-7 提取图像Alpha位图
// 图像缩放 public Bitmap getScaleBitmap() { BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources() .getDrawable(R.drawable.anims); Bitmap mBitmap = mBitmapDrawable.getBitmap(); int width = mBitmap.getWidth(); int height = mBitmap.getHeight(); Matrix matrix = new Matrix(); matrix.preScale(0.75f, 0.75f); Bitmap mScaleBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true); return mScaleBitmap; }
图7-8 图像缩放
// 图像扭转 public Bitmap getRotatedBitmap() { BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources() .getDrawable(R.drawable.anims); Bitmap mBitmap = mBitmapDrawable.getBitmap(); int width = mBitmap.getWidth(); int height = mBitmap.getHeight(); Matrix matrix = new Matrix(); matrix.preRotate(45); Bitmap mRotateBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true); return mRotateBitmap; }
图7-9 图像扭转
// 图像倾斜 public Bitmap getScrewBitmap() { BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources() .getDrawable(R.drawable.anims); Bitmap mBitmap = mBitmapDrawable.getBitmap(); int width = mBitmap.getWidth(); int height = mBitmap.getHeight(); Matrix matrix = new Matrix(); matrix.preSkew(1.0f, 0.15f); Bitmap mScrewBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true); return mScrewBitmap; }
图7-10 图像倾斜
4)图像倒影
为图像添加倒影下场之后,图像看起来会有立体感,更有真实感,在Android中使用Matrix类可以很轻易实现图像的倒影下场。主若是Matrix的preScale体例的使用,给它设置负数缩放比例,图像就会进行反转。然后经由过程设置Shader添加渐变下场。Java轨范代码如下文所示:
// 图像倒影 private Bitmap getReflectedBitmap() { BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources() .getDrawable(R.drawable.anims); Bitmap mBitmap = mBitmapDrawable.getBitmap(); int width = mBitmap.getWidth(); int height = mBitmap.getHeight(); Matrix matrix = new Matrix(); // 图像缩放,x轴变为原本的1倍,y轴为-1倍,实现图像的反转 matrix.preScale(1, -1); // 建树反转后的图像Bitmap对象,图像高是原图的一半。 // Bitmap mInverseBitmap = Bitmap.createBitmap(mBitmap, 0, height/2, // width, height/2, matrix, false); // 建树尺度的Bitmap对象,宽和原图一致,高是原图的1.5倍。 // 注重两种createBitmap的分歧 // Bitmap mReflectedBitmap = Bitmap.createBitmap(width, height*3/2, // Config.ARGB_8888); Bitmap mInverseBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, false); Bitmap mReflectedBitmap = Bitmap.createBitmap(width, height * 2, Config.ARGB_8888); // 把新建的位图作为画板 Canvas mCanvas = new Canvas(mReflectedBitmap); // 绘制图像 mCanvas.drawBitmap(mBitmap, 0, 0, null); mCanvas.drawBitmap(mInverseBitmap, 0, height, null); // 添加倒影的渐变下场 Paint mPaint = new Paint(); Shader mShader = new LinearGradient(0, height, 0, mReflectedBitmap.getHeight(), 0x70ffffff, 0x00ffffff, TileMode.MIRROR); mPaint.setShader(mShader); // 设置叠加模式 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); // 绘制遮罩下场 mCanvas.drawRect(0, height, width, mReflectedBitmap.getHeight(), mPaint); return mReflectedBitmap; }
下场如下文所示图所示:
图7-11 图像倒影
BitmapDrawable bd = (BitmapDrawable) getResources().getDrawable( R.drawable.default_1); Bitmap bitmap = bd.getBitmap(); int w = bitmap.getWidth(); int h = bitmap.getHeight(); Bitmap bm = Bitmap.createBitmap(w, h, Config.ARGB_8888); Canvas canvas = new Canvas(bm); Paint mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Style.STROKE); canvas.drawBitmap(bitmap, 0, 0, mPaint);
图7-12 第一步下场图
int deltX = 76; int deltY = 98; DashPathEffect dashStyle = new DashPathEffect( new float[] { 10, 5, 5, 5 }, 2);// 建树虚线边框样式 RectF faceRect = new RectF(0, 0, 88, 106); float[] faceCornerii = new float[] { 30, 30, 30, 30, 75, 75, 75, 75 }; Paint mPaint = new Paint();// 建树画笔 mPaint.setColor(0xFF6F8DD5); mPaint.setStrokeWidth(6); mPaint.setPathEffect(dashStyle); Path clip = new Path();// 建树路径 clip.reset(); clip.addRoundRect(faceRect, faceCornerii, Direction.CW);// 添加圆角矩形路径 canvas.save();// 保留画布 canvas.translate(deltX, deltY); canvas.clipPath(clip, Region.Op.DIFFERENCE); canvas.drawColor(0xDF222222); canvas.drawPath(clip, mPaint);// 绘制路径 canvas.restore();
图7-13 第二步下场
Rect srcRect = new Rect(0, 0, 88, 106); srcRect.offset(deltX, deltY); PaintFlagsDrawFilter dfd = new PaintFlagsDrawFilter( Paint.ANTI_ALIAS_FLAG, Paint.FILTER_BITMAP_FLAG); canvas.setDrawFilter(dfd); canvas.clipPath(clip);// 使用路径剪切画布 canvas.drawBitmap(bitmap, srcRect, faceRect, mPaint);
图7-13 第三部下场图