Android多媒体开发(一)——图片展示

1,198 阅读3分钟

背景

多媒体开发,包含图片,音频,视频等领域。近期参与的新项目,正好涉及在Android客户端上进行多媒体开发,借此一步一步尝试学习和整理资料。

第一步就从最简单的图片展示来入门:尝试用三种方式来展示图片——ImageView,自定义View,SurfaceView。

实现

ImageView

这个最简单,稍有Android基础的开发者都会,可以通过在layout文件中定义ImageView的时候指定src为对应图片,亦可在java代码中通过ImageView的setImageDrawable或者setImageBitmap来设置图片,用于展示。

代码过于简单,这里不细述。

自定义View

自定义View,就是要自定义View的三个方法,onMeasure, onLayout, onDraw,前两个方法用来定义View的size和位置,后一个onDraw才是绘制的具体实现,所以自定义View绘制图片,就要在onDraw中来绘制。

public class MyView extends View {
    private Bitmap mBitmap;
    private Paint mPaint;

    public MyView(Context context) {
        super(context);
        //读取图片为bitmap实例
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
        //Paint可以定义画笔的颜色粗细等,在画线条,形状等的时候生效,而在画图片的时候颜色粗细等属性无效,所以只需要new一个实例就好
        mPaint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //canvas意为“画布”,即是View的可绘制区域
        canvas.drawBitmap(mBitmap, 0, 0, mPaint);
    }
}

onDraw会View初始化后进行调用,将图片绘制到View上。

除此之外,View的postInvalidate方法也会导致重绘,调用onDraw。

SurfaceView

SurfaceView在Android系统算是比较复杂的存在,它与View有所不同。最大的区别就是 View只能在主线程渲染,SurfaceView则可以自定义渲染线程。
我们知道,如果在主线程做过于耗时的操作,超过16ms,就会引起掉帧甚至ANR。而SurfaceView可以不在主线程渲染,所以用SurfaceView来做渲染视频之类的耗时操作,就可以不影响到主线程的渲染。

public class SurfaceMainActivity extends Activity implements Callback {
    private SurfaceView mSurfaceView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.mSurfaceView = new SurfaceView(this);
        setContentView(mSurfaceView);
        //SurfaceView有自己的生命周期,不能直接使用,要通过callback监听到Surface在create之后,destroy之前,才能在其上绘制
        mSurfaceView.getHolder().addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        //Surface已经创建,可以绘制我们的图片了
        drawBitmap(holder);
    }

    private void drawBitmap(SurfaceHolder holder) {
        Bitmap bitmap = null;
        try {
        //从assets中读test.png创建bitmap实例
            bitmap = BitmapFactory.decodeStream(getAssets().open("test.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取画布
        Canvas canvas = holder.lockCanvas();
        //画一个大红色背景(清空画布)
        canvas.drawColor(Color.RED);
        if (bitmap != null) {
            //将图片绘制到画布上
            canvas.drawBitmap(bitmap,0,0,new Paint());
        }
        //完成绘制
        holder.unlockCanvasAndPost(canvas);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        //Surface销毁,在这之后,不能再获取画布绘制了
    }
}

以上是在SurfaceView上绘制一张图片的例子,如果是在surfaceCreated之后,另起一个独立的线程,将视频解析成一帧一帧绘制到Canvas上,那也就做成了一个视频播放器。