如何使用Canvas设置图片?以及从自定义View中获取Bitmap的方法
如何从自定义View获取Bitmap & 用Canvas绘制图片
一、从你的CircleIcon自定义View中获取Bitmap
要把自定义View的内容转成Bitmap,你可以在CircleIcon类里加个专门的方法,让View把绘制内容渲染到我们创建的Bitmap上,步骤很清晰:
- 在
CircleIcon类中添加获取Bitmap的方法:
public class CircleIcon extends View { // 你的原有代码(比如Paint定义、onDraw方法等) public Bitmap getViewBitmap() { // 创建和View当前尺寸匹配的Bitmap,ARGB_8888支持透明度,适配绝大多数场景 Bitmap bitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); // 创建关联这个Bitmap的Canvas,后续所有绘制操作都会落到这个Bitmap上 Canvas canvas = new Canvas(bitmap); // 手动调用View的draw方法,让它把内容画到我们的Canvas里 draw(canvas); return bitmap; } }
- 在Activity中调用这个方法获取Bitmap:
要注意得等View完成布局再调用(不然getMeasuredWidth()可能返回0),可以用post()来确保布局完成:
CircleIcon circleIcon = findViewById(R.id.your_circle_icon_id); circleIcon.post(new Runnable() { @Override public void run() { Bitmap viewBitmap = circleIcon.getViewBitmap(); // 这里就可以使用这个Bitmap了,比如显示到ImageView里 ImageView imageView = findViewById(R.id.target_image_view); imageView.setImageBitmap(viewBitmap); } });
二、用Canvas设置(绘制)图片
Canvas提供了几种绘制图片的方式,你可以根据需求选:
方式1:直接绘制Bitmap到Canvas
这是最基础的用法,适合把图片直接画在View的某个位置:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 先加载Bitmap(示例从资源文件加载,也可以从文件、网络等渠道获取) Bitmap imageBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.your_image); // 绘制图片:参数依次是Bitmap、左上角x坐标、左上角y坐标、Paint(可以传null) canvas.drawBitmap(imageBitmap, 0, 0, null); // 如果需要让图片适配View尺寸,用重载方法指定目标矩形即可 Rect targetRect = new Rect(0, 0, getMeasuredWidth(), getMeasuredHeight()); canvas.drawBitmap(imageBitmap, null, targetRect, null); }
方式2:用BitmapShader把图片作为纹理绘制到形状上
如果想把图片做成圆形(比如你的CircleIcon要改成图片圆形头像),可以用BitmapShader实现:
public class CircleIcon extends View { private Paint innerCircularPaint; private BitmapShader bitmapShader; private Bitmap imageBitmap; public CircleIcon(Context context) { super(context); init(); } // 其他构造方法... private void init() { innerCircularPaint = new Paint(Paint.ANTI_ALIAS_FLAG); // 加载图片并初始化BitmapShader imageBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.your_image); bitmapShader = new BitmapShader(imageBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 调整Shader缩放比例,让图片完美适配View尺寸 Matrix matrix = new Matrix(); float scale = Math.max(getMeasuredWidth()/(float)imageBitmap.getWidth(), getMeasuredHeight()/(float)imageBitmap.getHeight()); matrix.setScale(scale, scale); bitmapShader.setLocalMatrix(matrix); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int centerX = getMeasuredWidth()/2; int centerY = getMeasuredHeight()/2; int radius = Math.min(centerX, centerY); // 把Shader设置给Paint,绘制圆形时就会用图片填充 innerCircularPaint.setShader(bitmapShader); canvas.drawCircle(centerX, centerY, radius-1, innerCircularPaint); // 如果之后还要用这个Paint绘制不带图片的内容,记得重置Shader // innerCircularPaint.setShader(null); } }
小提醒:Bitmap是重量级对象,用完如果不再需要,记得调用
bitmap.recycle()释放内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Amit Ranjan




