Surface与SurfaceView、SurfaceHolder

一、Surface

Surface是一块屏幕的抽象表示,它允许一个应用程序在屏幕上绘制内容。

在Android系统中,一个Surface可以与一个Canvas或OpenGL ES进行交互,从而在屏幕上显示出图形或动画。Surface提供了一个BufferQueue,其中包含了一组Surface上的图像或动画帧,应用程序可以向这个BufferQueue中添加图像或动画帧,而Surface则会把这些图像或动画帧显示出来。当一个图像或动画帧被显示出来后,它就从BufferQueue中移除了。

二、SurfaceView

SurfaceView是Android系统中用于显示Surface的一种视图控件。它通过一个SurfaceHolder对象来控制Surface的创建、销毁和绘制等操作。

与常规的View控件不同,SurfaceView通过子线程来进行绘制操作,这样可以避免在主线程中进行复杂的绘制操作而导致UI卡顿。同时,SurfaceView提供了onDraw()方法,开发者可以在这个方法中进行自己的绘制操作。

三、SurfaceHolder

SurfaceHolder是SurfaceView内部用于控制Surface的一个接口。通过SurfaceHolder,应用程序可以进行Surface的创建、销毁、锁定、解锁和绘制等操作。

SurfaceHolder提供了三个方法,分别是:

1. getSurface():获取Surface对象。

2. lockCanvas():获取Surface上的Canvas对象,并锁定Surface,这样其他线程就无法访问Surface了。

3. unlockCanvasAndPost():解锁Surface,并把Canvas上的内容提交到Surface中。

具体使用方法如下:

```Java

SurfaceHolder holder = surfaceView.getHolder();

Canvas canvas = holder.lockCanvas();

// 在Canvas上进行绘制操作

holder.unlockCanvasAndPost(canvas);

```

四、使用方法

首先需要在布局文件中定义SurfaceView组件:

```XML

android:id="@+id/surfaceView"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

```

接着在Activity中获取SurfaceView对象,并设置SurfaceHolder.Callback:

```Java

SurfaceView surfaceView = findViewById(R.id.surfaceView);

surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {

@Override

public void surfaceCreated(SurfaceHolder holder) {

// Surface被创建时调用

}

@Override

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

// Surface尺寸发生改变时调用

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

// Surface被销毁时调用

}

});

```

在surfaceCreated()方法中可以获取SurfaceHolder对象,并使用lockCanvas()方法获取Canvas对象在上面进行绘制操作,并最终使用unlockCanvasAndPost()方法将内容提交到Surface中,代码如下:

```Java

@Override

public void surfaceCreated(SurfaceHolder holder) {

Canvas canvas = holder.lockCanvas();

// 在Canvas上进行绘制操作

holder.unlockCanvasAndPost(canvas);

}

```

注意:在使用完Canvas后一定要解锁Surface,否则其他线程无法访问Surface,并且会出现黑屏等异常情况。

五、案例说明

下面我们来实现一个简单的SurfaceView动画效果,每次刷新Surface时,小球向上移动一段距离。

首先定义一个Ball类,用于表示小球:

```Java

public class Ball {

public float x; // 小球的x坐标

public float y; // 小球的y坐标

public float radius; // 小球的半径

public Ball(float x, float y, float radius) {

this.x = x;

this.y = y;

this.radius = radius;

}

}

```

然后在Activity中定义一个Ball数组,并在surfaceCreated()方法中对小球进行初始化:

```Java

public class MainActivity extends AppCompatActivity {

private SurfaceView surfaceView;

private Ball[] balls = new Ball[10];

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

surfaceView = findViewById(R.id.surfaceView);

surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {

@Override

public void surfaceCreated(SurfaceHolder holder) {

// 初始化小球

float radius = 50;

float y = surfaceView.getHeight() - radius;

float xInterval = (surfaceView.getWidth() - radius * 2) / (balls.length - 1);

for (int i = 0; i < balls.length; i++) {

float x = radius + i * xInterval;

balls[i] = new Ball(x, y, radius);

}

// 启动子线程不断重绘

new Thread(new Runnable() {

@Override

public void run() {

while (true) {

Canvas canvas = null;

try {

canvas = surfaceView.getHolder().lockCanvas();

synchronized (surfaceView.getHolder()) {

draw(canvas); // 在Canvas上进行绘制

}

} catch (Exception e) {

e.printStackTrace();

} finally {

if (canvas != null) {

surfaceView.getHolder().unlockCanvasAndPost(canvas); // 提交到Surface中

}

}

try {

Thread.sleep(16); // 控制刷新频率

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

}

@Override

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

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

}

});

}

private void draw(Canvas canvas) {

canvas.drawColor(Color.WHITE); // 用白色清空画布

Paint paint = new Paint();

paint.setColor(Color.RED);

for (int i = 0; i < balls.length; i++) {

Ball ball = balls[i];

ball.y -= 5; // 让小球向上移动一段距离

canvas.drawCircle(ball.x, ball.y, ball.radius, paint);

}

}

}

```

在draw()方法中,我们使用Canvas的drawCircle()方法来绘制小球,在每次刷新Surface时让小球向上移动一段距离,从而实现了一个简单的小球动画效果。同时,在surfaceCreated()方法中启动一个子线程,不断地重绘Surface,从而实现动画的播放。

通过这个例子,我们可以了解到Surface、SurfaceView和SurfaceHolder之间的关系,以及如何在SurfaceView中使用Surface进行绘制操作。 如果你喜欢我们三七知识分享网站的文章, 欢迎您分享或收藏知识分享网站文章 欢迎您到我们的网站逛逛喔!https://www.37seo.cn/

点赞(42) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿
发表
评论
返回
顶部