绘制图片
注意硬件加速造成的影响。
drawPicture
简介
把 Canvas 绘制点,线,矩形等诸多操作用 Picture 录制下来,下次需要的时候拿来就能用,使用Picture
相比于再次调用绘图API,开销更小,也就是说对于重复的操作可以更加节省开销。
相关API
相关方法 | 简介 |
---|---|
public int getWidth () | 获取宽度 |
public int getHeight () | 获取高度 |
public Canvas beginRecording (int width, int height) | 开始录制 (返回一个Canvas,在Canvas中所有的绘制都会存储在Picture中) |
public void endRecording () | 结束录制 |
public void draw (Canvas canvas) | 将Picture中内容绘制到Canvas中 |
public static Picture createFromStream (InputStream stream) | (已废弃)通过输入流创建一个Picture |
public void writeToStream (OutputStream stream) | (已废弃)将Picture中内容写出到输出流中 |
录制
将一些 Canvas 操作用Picture
存储起来,不会直接显示在屏幕上的。
// 1.创建Picture
private Picture mPicture = new Picture();
---------------------------------------------------------------
// 2.录制内容方法
private void recording() {
// 开始录制 (接收返回值Canvas)
Canvas canvas = mPicture.beginRecording(500, 500);
// 创建一个画笔
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.FILL);
// 在Canvas中具体操作
// 位移
canvas.translate(250,250);
// 绘制一个圆
canvas.drawCircle(0,0,100,paint);
mPicture.endRecording();
}
---------------------------------------------------------------
// 3.在使用前调用(我在构造函数中调用了)
public Canvas3(Context context, AttributeSet attrs) {
super(context, attrs);
recording(); // 调用录制
}
绘制
简介
把录制的内容显示出来的方式有:
序号 | 简介 |
---|---|
1 | 使用Picture提供的draw方法绘制。 |
2 | 使用Canvas提供的drawPicture方法绘制。 |
3 | 将Picture包装成为PictureDrawable,使用PictureDrawable的draw方法绘制。 |
以上几种方法主要区别:
主要区别 | 分类 | 简介 |
---|---|---|
是否对Canvas有影响 | 1有影响,2、3不影响 | 此处指绘制完成后是否会影响Canvas的状态(Matrix clip等) |
可操作性强弱 | 1可操作性较弱,2、3可操作性较强 | 此处的可操作性可以简单理解为对绘制结果可控程度。 |
1. 使用Picture提供的draw方法绘制
PS :这种方法在比较低版本的系统上绘制后可能会影响Canvas
状态,所以这种方法一般不会使用。
// 将Picture中的内容绘制在Canvas上
mPicture.draw(canvas);
2. 使用Canvas提供的drawPicture方法绘制
和使用Picture
的draw()
不同, Canvas 的drawPicture()
不会影响 Canvas 状态。
drawPicture()
有三种方法:
public void drawPicture (Picture picture);
public void drawPicture (Picture picture, Rect dst);
public void drawPicture (Picture picture, RectF dst);
canvas.drawPicture(mPicture,new RectF(0,0,mPicture.getWidth(),200));
对照上一张图片,可以比较明显的看出,绘制的内容根据选区进行了缩放。
3. 使用PictureDrawable的draw方法绘制
// 包装成为Drawable
PictureDrawable drawable = new PictureDrawable(mPicture);
// 设置绘制区域 -- 注意此处所绘制的实际内容不会缩放
// 此处setBounds是设置在画布上的绘制区域,并非根据该区域进行缩放,也不是剪裁Picture,每次都从Picture的左上角开始绘制。
drawable.setBounds(0,0,250,mPicture.getHeight());
// 绘制
drawable.draw(canvas);
drawBitmap
获取Bitmap方式
序号 | 获取方式 | 备注 |
---|---|---|
1(少用) | 通过Bitmap创建 | 复制一个已有的Bitmap(新Bitmap状态和原有的一致) 或者 创建一个空白的Bitmap(内容可改变) |
2 | 通过BitmapDrawable获取 | 从资源文件 内存卡 网络等地方获取一张图片并转换为内容不可变的Bitmap |
3(常用) | 通过BitmapFactory获取 | 从资源文件 内存卡 网络等地方获取一张图片并转换为内容不可变的Bitmap |
通过BitmapFactory从不同位置获取Bitmap
资源文件(drawable/mipmap/raw)
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),R.raw.bitmap);
资源文件(assets)
Bitmap bitmap=null;
try {
InputStream is = mContext.getAssets().open("bitmap.png");
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
内存卡文件
Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/bitmap.png");
网络文件
// 此处省略了获取网络输入流的代码
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();
绘制Bitmap
方法
// 第一种:
public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint)
// 第二种:在绘制时指定了图片左上角的坐标(距离坐标原点的距离)
public void drawBitmap (Bitmap bitmap, float left, float top, Paint paint)
// 第三种:
public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint)
第一种
在 Canvas 坐标原点处绘制。
// 后两个参数(matrix, paint)是在绘制的时候对图片进行一些改变,如果只是需要将图片内容绘制出来只需要用默认构造的就可以了
canvas.drawBitmap(bitmap,new Matrix(),new Paint());
第二种
可以在绘制时指定图片左上角的坐标(距离 Canvas 坐标原点的距离)。
canvas.drawBitmap(bitmap,200,500,new Paint());
第三种和第四种
名称 | 作用 |
---|---|
Rect src | 指定绘制图片的区域 |
Rect dst 或 RectF dst | 指定图片在屏幕上显示(绘制)的区域 |
// 将画布坐标系移动到画布中央
canvas.translate(mWidth/2,mHeight/2);
// 指定图片绘制区域(左上角的四分之一)
Rect src = new Rect(0,0,bitmap.getWidth()/2,bitmap.getHeight()/2);
// 指定图片在屏幕上显示的区域
Rect dst = new Rect(0,0,200,400);
// 绘制图片
canvas.drawBitmap(bitmap,src,dst,null);
绘制文字
方法
// 第一类:只能指定文本基线位置(基线x默认在字符串左侧,基线y默认在字符串下方)。
public void drawText(String text, float x, float y, Paint paint)
public void drawText(String text, int start, int end, float x, float y, Paint paint)
public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint)
public void drawText(char[] text, int index, int count, float x, float y, Paint paint)
// 第二类:可以分别指定每个文字的位置。
public void drawPosText(String text, float[] pos, Paint paint)
public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint)
// 第三类:指定一个路径,根据路径绘制文字。
public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)
public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint)
Paint文本相关常用方法表
标题 | 相关方法 | 备注 |
---|---|---|
色彩 | setColor setARGB setAlpha | 设置颜色,透明度 |
大小 | setTextSize | 设置文本字体大小 |
字体 | setTypeface | 设置或清除字体样式 |
样式 | setStyle | 填充(FILL),描边(STROKE),填充加描边(FILL_AND_STROKE) |
对齐 | setTextAlign | 左对齐(LEFT),居中对齐(CENTER),右对齐(RIGHT) |
测量 | measureText | 测量文本大小(注意,请在设置完文本各项参数后调用) |
创建文本画笔
Paint textPaint = new Paint(); // 创建画笔
textPaint.setColor(Color.BLACK); // 设置颜色
textPaint.setStyle(Paint.Style.FILL); // 设置样式
textPaint.setTextSize(50); // 设置字体大小
第一类(drawText)
一
// 文本(要绘制的内容)
String str = "ABCDEFG";
// 参数分别为 (文本 基线x 基线y 画笔)
canvas.drawText(str,200,500,textPaint);
图中字符串下方的红线是基线y,基线x未在图中画出。
二、三
// 文本(要绘制的内容)
String str = "ABCDEFG";
// 参数分别为 (字符串 开始截取位置 结束截取位置 基线x 基线y 画笔)
canvas.drawText(str,1,3,200,500,textPaint);
四
// 字符数组(要绘制的内容)
char[] chars = "ABCDEFG".toCharArray();
// 参数为 (字符数组 起始坐标 个数 基线x 基线y 画笔)
canvas.drawText(chars,1,3,200,500,textPaint);
第二类(drawPosText)
缺点
序号 | 反对理由 |
---|---|
1 | 必须指定所有字符位置,否则直接crash掉,反人类设计 |
2 | 性能不佳,在大量使用的时候可能导致卡顿 |
3 | 不支持emoji等特殊字符,不支持字形组合与分解 |
一
示例
String str = "SLOOP";
canvas.drawPosText(str,new float[]{
100,100, // 第一个字符位置
200,200, // 第二个字符位置
300,300, // ...
400,400,
500,500
},textPaint);
二
省略。
第三类(drawTextOnPath)
TODO: