Android自定义控件开发入门与实战(15)SurfaceView

本文详细介绍了如何在Android中使用Bitmap和Canvas进行图像绘制,特别是展示了如何通过SurfaceView的双缓冲技术实现图像的局部移动和局部更新,以及LRU缓存策略的应用。作者还讨论了为何需要清屏操作和不同情况下画布区域的选择。
摘要由CSDN通过智能技术生成

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_jojo3);

bitmapBg = Bitmap.createScaledBitmap(bitmap, mWidth, (int) mSurfaceHeight, true);

(2)如何在屏幕上只画出图像的一部分?

Canvas::drawBitmap中有这样一个函数:

public void drawBitmap(Bitmap bitmap,float left,float top,Paint paint)

这个函数可以指定开始绘制图片的左上角位置。其中left、top就是指从Bitmap的哪个左上角点开始绘制,这样我们就可以指定绘制图片的一部分了。

(3)如何实现Bitmap的左右移动?

我们默从Bitmap的左上角(0,0)开始绘制,然后根据每次的步近距离向右移动,当移动到底时,再返回向左移动,核心代码如下:

//开始绘制的图片的x坐标

private int mBitposX;

//背景移动状态

private enum State {

LEFT, RIGHT

}

//默认为向左

private State state = State.LEFT;

//背景画布移动步伐,设置为1表示每次只移动1px,越大表明移动的越快

private final int BITMAP_STEP = 1;

private void DrawView() {

mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

mCanvas.drawBitmap(bitmapBg, mBitposX, 0, null);

//滚动效果

switch (state) {

case LEFT:

//画布左移

mBitposX -= BITMAP_STEP;

break;

case RIGHT:

mBitposX += BITMAP_STEP;

break;

default:

break;

}

if (mBitposX <= -mSurfaceWidth / 2) {

state = State.RIGHT;

}

if (mBitposX >= 0) {

state = State.LEFT;

}

}

然后我们需要在初始化的时候就让背景开始运动,所以要添加Surface监听,用flag作为开始、结束动画的标识,在生命周期中使用:

public AnimationSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

surfaceHolder = getHolder();

surfaceHolder.addCallback(new SurfaceHolder.Callback() {

@Override

public void surfaceCreated(SurfaceHolder holder) {

flag = true;

startAnimation();

}

@Override

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

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

flag = false;

}

});

}

然后startAnimation函数用来打开动画:

private void startAnimation() {

mSurfaceWidth = getWidth();

mSurfaceHeight = getHeight();

int mWidth = (int) (mSurfaceWidth * 3 / 2);

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_jojo3);

bitmapBg = Bitmap.createScaledBitmap(bitmap, mWidth, (int) mSurfaceHeight, true);

thread = new Thread(new Runnable() {

@Override

public void run() {

while (flag) {

mCanvas = surfaceHolder.lockCanvas();

DrawView();

surfaceHolder.unlockCanvasAndPost(mCanvas);

try {

Thread.sleep(50);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

});

thread.start();

}

为了减轻主线程的计算负担,我们单独开启一个线程来执行绘图操作;绘图完成后,我们延缓了50ms再进行下次绘图,这样从效果上来看就是一步步移动的。

3、SurfaceView双缓冲技术

(1)概述

SurfaceView的双缓冲技术需要两个图形缓冲区支持,一个是前端缓冲区,一个是后端缓冲区。

前端区对应当前屏幕正在显示的内容,后端缓冲区是接下来渲染的图形缓冲区。

**我们通过surfaceHolder.lockCanvas()函数获得的缓冲区是后端缓冲区。

当绘图完成后,调用surfaceHolder.unlockCanvasAndPost(mCanvas)函数将后端缓冲区与前端缓冲区交换,后端缓冲区变前端缓冲区。**

而原来的前端缓冲区则变成后端缓冲区,等待下一次srufaceHolder.lockCanvas()函数调用返回给用户使用,如此往复。

上面的机制让绘制的效率大大的提高,但这样也产生了一个问题&#x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值