内容简介:在 Android 音视频开发学习思路 里面,我们写到了,想要逐步入门音视频开发,就需要一步步的去学习整理,并积累。本文是音视频开发指南的第一篇。 对应的要学习的内容是:在 Android 平台绘制一张图片,使用3 种不同的 API,ImageView、SurfaceView、自定义 View。这个想必做过Android开发的都知道如何去绘制了:很轻松,在界面上清晰的看到养眼的美女:
在 Android 音视频开发学习思路 里面,我们写到了,想要逐步入门音视频开发,就需要一步步的去学习整理,并积累。本文是音视频开发指南的第一篇。 对应的要学习的内容是:在 Android 平台绘制一张图片,使用3 种不同的 API,ImageView、SurfaceView、自定义 View。
ImageView 绘制图片
这个想必做过Android开发的都知道如何去绘制了:
// ImageView 加载几种来源 //(1) drawable/mipmap 中通过 R.drawabe.xxx 加载图片资源 //(2) assests或者sdcard的路径的资源 // 这里我以 assests 代表来加载资源 ImageView customImageView = findViewById(R.id.img_middle); customImageView.setImageBitmap(Util.getImageFromAssetsFile(this, "prettygirl.png")); // Util.getImageFromAssetsFile(this, "prettygirl.png") public static Bitmap getImageFromAssetsFile(Context context, String fileName) { Bitmap image = null; AssetManager am = context.getResources().getAssets(); try { InputStream is = am.open(fileName); image = BitmapFactory.decodeStream(is); is.close(); } catch (IOException e) { e.printStackTrace(); } return image; } 复制代码
很轻松,在界面上清晰的看到养眼的美女:
自定义 View 绘制图片
有些时候我们需要加载图片需要自定义View来加载图片,通过上边加载图片的方式加上我自己自定义View 经验,我们很快能写出下边通过自定义View的代码来加载图片。
/** * 自定义View 显示图片 */ public class CustomImageView extends View { private Bitmap mBitmap; private Paint mPaint = new Paint(); ··· private void init() { initPaint(); } private void initPaint() { mPaint = new Paint(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setFlags(Paint.ANTI_ALIAS_FLAG); //设置抗锯齿 mPaint.setAntiAlias(true); } public void setBitmap(Bitmap bitmap) { mBitmap = bitmap; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mBitmap == null) { return; } canvas.drawBitmap(mBitmap, 0, 0, mPaint); } } 复制代码
SurfaceView 绘制图片
这个比 ImageView 绘制图片稍微复杂一点点,接下来呢,说说自己对它的理解
定义
SurfaceView是View的一个特殊子类,它的目的是 另外提供一个线程 进行绘制操作。
它的特性是:可以在主线程之外的线程中向屏幕绘图上。这样可以避免画图任务繁重的时候造成主线程阻塞,从而提高了程序的反应速度。
实现
首先继承SurfaceView并实现SurfaceHolder.Callback接口,使用接口的原因:因为使用SurfaceView 有一个原则,所有的绘图工作必须得在Surface 被创建之后才能开始(Surface—表面,这个概念在 图形编程中常常被提到。基本上我们可以把它当作显存的一个映射,写入到Surface 的内容。
可以被直接复制到显存从而显示出来,这使得显示速度会非常快),而在Surface 被销毁之前必须结束。所以Callback 中的surfaceCreated 和surfaceDestroyed 就成了绘图处理代码的边界。
需要重写的方法如下:
//在surface的大小发生改变时激发、 public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){} //在创建时激发,一般在这里调用画图的线程。 public void surfaceCreated(SurfaceHolder holder){} //销毁时激发,一般在这里将画图的线程停止、释放。 public void surfaceDestroyed(SurfaceHolder holder) {} 复制代码
使用SurfaceView大概流程:
- 继承SurfaceView并实现SurfaceHolder.Callback接口
- SurfaceView.getHolder()获得SurfaceHolder对象
- SurfaceHolder.addCallback(callback)添加回调函数
- SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布
- Canvas绘画
- SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。
这里用到了一个类SurfaceHolder,可以把它当成surface的控制器,就好比我们常用的MVC 设计模式,用来操纵Surface。处理它的Canvas上画的效果和动画,控制表面、大小、像素等。下面我说几个需要注意的方法:
// 给SurfaceView当前的持有者一个回调对象。 abstract void addCallback(SurfaceHolder.Callback callback); // 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。 abstract Canvas lockCanvas(); // 锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容。 // 相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度。 abstract Canvas lockCanvas(Rect dirty); // 结束锁定画图,并提交改变。 abstract void unlockCanvasAndPost(Canvas canvas); 复制代码
注意:每次利用SurfaceHolder获得画布时,前一次的内容将会保留。
我这里贴一下重要部分的代码:
/** * 自定义SurfaceView 绘制图片 */ public class CustomSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable { ···· private void init() { mHolder = getHolder(); mHolder.addCallback(this); mPaint = new Paint(); //获取焦点 setFocusable(true); setFocusableInTouchMode(true); //设置常量 setKeepScreenOn(true); } @Override public void surfaceCreated(SurfaceHolder holder) { isRunning = true; mThread = new Thread(this); mThread.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { isRunning = false; } @Override public void run() { //循环绘制 while (isRunning) { draw(); } } private void draw() { try { mCanvas = mHolder.lockCanvas(); if (mCanvas != null) { mCanvas.drawBitmap(Util.getImageFromAssetsFile(mContext, PICTURE_NAME), 0, 0, mPaint); } } catch (Exception e) { e.printStackTrace(); } finally { if (mCanvas != null) { //释放canvas mHolder.unlockCanvasAndPost(mCanvas); } } } } 复制代码
源码地址(image包名下):https://github.com/StudyLifeTime/basicvideotutorial
总结
最后总结一下学习这三种加载方式,自定义View 和 ImageView 加载方式大同小异,就是自定义View注意画笔的抗锯齿操作,然后绘制图片如果很浪费资源的情况下推荐使用 SurfaceView ,毕竟是在工作线程里绘制不会影响到主线程的阻塞问题。
编程·思维·职场
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。