Android开发&Canvas

原创 2015年11月18日 15:19:46

若非专业设置游戏界面或者从事美工人员,对于2D图形绘制工具Canvas,只需懂得基本用法就好,技术人员主要是为了实现功能,Canvas也主要是在自定义view及其子类时,绘制界面所用。
canvas绘图被人形象的描述为“画布”,这样理解也无可厚非,画笔“paint”工作的地方就是画布。
有时候需要制作一些图形,现有控件是无法办到的,这时需要我们新建view类,然后将内容画到视图中,最常用的就是重写draw方法,这个方法就是显示界面时候你指定要”画“的东西。

class DrawView extends View {
    public DrawView(Context context) {
        super(context);
    }

    @Override
    public void draw(Canvas canvas){
        super.draw(canvas);//参数传入的画布,明显还有其他地方需要引用,因此不要自己去新建canvas了。
        int width =canvas.getWidth();//获取画布的宽;
        int height = canvas.getHeight();//获取画布的高;
        Paint paint = new Paint();//新建画笔类;
        paint.setStyle(Paint.Style.STROKE);//设置画笔类型为stroke,表示只描边
        paint.setAlpha(250);//设置——不——透明度,为0表示透明。
        paint.setAntiAlias(true);//抗锯齿,为了让画出来的线更平滑。
        paint.setStrokeWidth(5);//设置画笔线的粗细,是以像素为单位的,例如红米手机像素为720*1280
        paint.setColor(Color.BLUE);//设置画笔颜色
        canvas.drawPoint(100,100,paint);//在100,100的坐标画一个点,点的大小可以通过设置画笔线的粗细来调节。
   }
}

如果在linearLayout中横向排列同时设置了一个控件的width=“wrap_content”和weight,那么会优先设置控件的宽度大于等于wrap_content;
基本的canvas和paint用法,网上可以自己找,很多人都有介绍,这里只是画一个点示范,要注意的是,坐标轴是以你自定义的控件的左上角为坐标原点的,如果你控件不是充满整个屏幕,那么canvas的width和height就不是为屏幕的像素了,另外如果你重写了ontouch方法,会发现坐标会有负值出现

为了学习canvas,我自己制作了一个涂鸦板,手指接触屏幕或者滑动时,会在上面留下轨迹,然后可以将画板以图片文件的形式保存下来,且如果再次打开画板,可以将保存的图片文件再显示到画板上,功能大概就是如此,且看代码。

class DrawView extends View {
public DrawView(Context context) {
super(context);
}

@Override
public void draw(Canvas canvas){
super.draw(canvas);
int width =canvas.getWidth();
int height = canvas.getHeight();
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setAlpha(250);
paint.setAntiAlias(true);
paint.setStrokeWidth(5);
paint.setColor(Color.BLUE);

//从这里往下看->
File file=new File(Environment.getExternalStorageDirectory() + "/" + "bitmap.jpg");
if(file.exists()) {
try {
Bitmap b=BitmapFactory.decodeFile(file.getPath());
canvas.setBitmap(b);
} catch (Exception e) {
Toast.makeText(DrawBitmap.this,e.toString(),Toast.LENGTH_LONG).show();
}
}
}
}

为了省事我把很多的代码删除了,所以有些变量看起来跟没有定义一样,没关系,我们直接看。
当有文件bitmap存在时,就通过BitmapFactory.decodeFile()生成bitmap位图,然后直接通过canvas.setBitmap()方法,把位图设为画布的背景,这时会有异常:
IllegalStateException
查看源码发现是因为setBitmap()方法参数必须是可以改变的位图:

public void setBitmap(@Nullable Bitmap bitmap) {
    if (!bitmap.isMutable()) {
            throw new IllegalStateException();
        }
    }
}
//注意这代码都是截取的,因此发现跟源码不同不要惊异。

然后我改变源码,先把bitmap变为isMutable的,再传入:

canvas.setBitmap(b.copy(Bitmap.Config.ARGB_8888, true));

嗯,它又抛出异常:UnsupportOperationException

没办法,我只能再上百度,有大神说这是因为开启了硬件加速,所以导致异常,于是我再然后在Manifest.xml的application中加上android:hardwareAccelerated=”false”,这是关闭硬件加速,结果没有错误了,界面却又无法显示了,手指接触屏幕也不会有痕迹出现,.还得去查看硬件加速的问题……>>>>>>>>>

<application
    android:hardwareAccelerated="false"

还有的童鞋发现在copy之后,因为内存中会存在多张图片,会导致内存溢出OOM,嗯,好吧,如果以后想用setBitmap方法,还是省省吧,改用drawBitmap比较好一点,不会有这么多的麻烦。
不过需要注意的是,使用drawbitmap时,要不能使用过大的图片,否则会导致OOM,一般300Kb的就可以,再大就有可能导致画面卡顿甚至卡死,不过我发现一个奇怪的现象,在我的涂鸦界面中,如果把传入的
copy之后再drawBitmap,虽然界面还是会卡顿,但不会直接退出。

bitmap大小=图片长度(px)*图片宽度(px)*单位像素占用的字节数
单位像素所占字节数就是图片的色彩模式,安卓默认为四个字节。
在BitmapFactory.Options.inPreferredConfig这里可以找到,一共有4种, ARGB代表:A 透明度 , R 红色, G 绿色, B 蓝色。

图片的压缩方法可以参考以下博客:
android图片压缩的三种算法

这是质量压缩算法的实现:

File file=new File(Environment.getExternalStorageDirectory() + "/" + "bitmap.jpg");
if (file.exists()) {
 int p=90;
 Bitmap b=BitmapFactory.decodeFile(file.getPath());
 while(b.getByteCount()>1024*300&&p>20){
 //这里为了明显对比,进行的是破坏性实验,把图片最低压缩为30%,可以自己实验看下效果。
     try {
         b.compress(Bitmap.CompressFormat.JPEG,p--,new FileOutputStream(file));
         b=BitmapFactory.decodeFile(file.getPath());
     } catch (FileNotFoundException e) {
         Toast.makeText(MainActicity.this,"bitmap can't compress",Toast.LENGTH_SHORT).show();
         break;
     }
 }
}

按比例压缩方法:

private Bitmap compressPicture(String pathName,int height,int width){//按比例压缩
    BitmapFactory.Options options=new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    //设置options只读取图片的大小。
    Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/"+pathName,options);//此时返回bm为空,但必须有这一步,这是获取图片options的。
    options.inJustDecodeBounds=false;
    int h=options.outHeight;
    int w=options.outWidth;
    //得到图片的宽高,
    int zip= h/height>w/width?h/height:w/width;
    options.inSampleSize=zip;//设置缩放的比例,此时改变了像素大小,那么bitmap大小就会改变。
    bitmap=BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/"+pathName,options);
    return bitmap;
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

android开发 之 Canvas之画布操作

一.Canvas的常用操作速查表 操作类型 相关API 备注 绘制颜色 drawColor, drawRGB, drawARGB 使用单...

Android开发-----03-使用Canvas绘制虚线……

本章只关注绘制虚线,不关注Canvas的其它操作。 Android中,Canvas的功能都非常强大,一般情况下,用到了就去研究,用不到就懒得理会它。但是随着项目的需求不断增加,再怎么不想了解Canv...

android开发笔记之多媒体—Canvas的相关方法

——Canvas相关方法 ——画线:canvas.drawLine(20, 20, 200, 200, paint) ——画矩形:canvas.drawRect(20, 20, 200, 20...

android开发之 Canvas

由于在网络上找到关于Canvas的使用都比较抽象,也许是我的逻辑思维不太好吧,总是感觉理解起来比较困难,     尤其是对save()和restore()方法的使用。本篇文章的内容就是对Canvas...

Android开发之Canvas及高级使用

前言:相信你看了前几篇的博客,你对paint渲染以及滤镜有一个初步的认识,今天我们来综合一下canvas的绘制,path的用法,以及Canvas的转换。

【Android开发】图形图像处理技术-常用绘图类之Canvas类

Canvans类代表画布,通过该类提供的方法,可以绘制各种图形(如矩形、圆形和线条等)。通常情况下,要在Android中绘图,需要先创建一个继承自View类的视图,并且在该类中重写onDraw(Can...

Android开发,关于Canvas的使用,绘图的各种用法

本文是在CrazyAndroid上摘抄下来的,囊括了Cavas,Paint,Path,Shader的各种用法,对于初学Android绘图的同学(比如我)来说,还是很有用处的 public class...

Android开发--图形图像与动画(一)--Paint和Canvas类

* Paint类  * Paint类代表画笔,用来描述图形的颜色和风格,如线宽,颜色,透明度和填充效果等信息。  * 使用Paint类时,需要先创建该类的对象,可以通过该类的构造函数实现。通常情况...

Android开发笔记之Canvas的相关方法

一.Canvas在Android中是提供画图操作的API,你可以理解它为一个画板,他提供了很多画画操作,你在画布上铺上画纸就可以借助画板工具来进行线条,形状等等进行画画。 二.每次要进行画画之前都需...

Android开发--Canvas高级使用

1.绘制路径   Canvas类中也提供了绘制路径的功能,通过canvas.drawPath方法,可以画出封闭路径和开放路径,并可以再路径上实现一些特殊的效果。 -----------------...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)