Android开发&Canvas
来源:互联网 发布:苹果app下载不了软件 编辑:程序博客网 时间:2024/04/29 21:52
若非专业设置游戏界面或者从事美工人员,对于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);}@Overridepublic 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
- Android开发&Canvas
- Android开发 之 Canvas
- Android开发:canvas.drawTextOnPath()无效
- Android开发--Canvas高级使用
- Android游戏开发基础part2--Canvas画布
- Android 游戏开发之Canvas画布
- android开发--Canvas清屏只需三句话
- android开发--Canvas清屏只需三句话
- 高性能Android Canvas游戏开发
- 【canvas】Android游戏开发坐标系统
- Android 游戏开发之Canvas画布
- Android开发之Canvas及高级使用
- android开发 之 Canvas之画布操作
- android开发 之 Canvas绘制文字,图片
- High Performance Canvas Game for Android(高性能Android Canvas游戏开发)
- Android Canvas
- Android Canvas
- 在Ubuntu 10.04中文版下Qt编程,使用unixODBC和FreeTDS连接MS SQL Server 2005,并且中文不出现乱码的方法
- texeview设置不同文字的点击事件
- Linux时间函数之gettimeofday()函数之使用方法
- C语言中强制类型转换的总结
- Java 泛型中? super T和? extends T的区别
- Android开发&Canvas
- 在linux下用tomcat部署java web项目的过程与注意事项
- Xcode6之后添加 .pch 文件
- 【Leet Code】80. Remove Duplicates from Sorted Array II---Medium
- Kibana User Guide [4.2] » Introduction
- 浅谈如何提高服务器并发处理能力(来自某位大牛的博客)
- ID_ANDROID_CONTENT
- iOS应用国际化教程(2014版)
- VMWare 解决“intel VT-x 处于禁用状态”的问题