Surface与SurfaceView、SurfaceHolder

一、Surface

Surface是Android中用于显示图像的一个抽象类,它代表了一个可以被绘制的图像目标。它实现了SurfaceHolder接口,可以提供一个Canvas用于绘制内容。Surface是在窗口系统中表示什么显示什么的一个抽象概念,可以是屏幕、应用界面或者图片等等。

二、SurfaceView

SurfaceView是一个用于绘制2D图形的控件,它继承自View。与普通的View不同的是,SurfaceView有一个独立的Surface,可以在非UI线程中更新图像,因此可以流畅地展现动画效果。使用SurfaceView可以达到更高的帧率,使得图像更加流畅。

三、SurfaceHolder

SurfaceHolder是Surface的持有者,用于管理Surface的生命周期以及控制Surface对外显示。SurfaceHolder提供了一组接口,可用于获取Canvas、设置Surface尺寸、注册Surface.Callback等操作,这样可以对Surface进行更加灵活的控制。

四、使用方法

1.创建SurfaceView并设置大小

在XML布局文件中添加SurfaceView控件,设置它的宽和高,布局文件如下:

```xml

android:id="@+id/surface_view"

android:layout_width="match_parent"

android:layout_height="match_parent" />

```

或者在Java代码中动态添加SurfaceView,然后设置它的宽和高,示例代码如下:

```java

SurfaceView surfaceView = new SurfaceView(this);

FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(

ViewGroup.LayoutParams.MATCH_PARENT,

ViewGroup.LayoutParams.MATCH_PARENT);

surfaceView.setLayoutParams(lp);

```

2.获取SurfaceHolder

通过SurfaceView获取SurfaceHolder,示例代码如下:

```java

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

SurfaceHolder surfaceHolder = surfaceView.getHolder();

```

3.注册SurfaceCallback

注册SurfaceCallback,以便回调Surface的生命周期和Surface状态的变化。示例代码如下:

```java

SurfaceHolder surfaceHolder = surfaceView.getHolder();

surfaceHolder.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销毁时回调

}

});

```

4.在Surface中绘制内容

在SurfaceView的回调方法surfaceCreated()中,可以获取到Surface对象,利用Canvas绘制图形。绘制完成后,通过SurfaceHolder.unlockCanvasAndPost()方法提交到Surface中显示。示例代码如下:

```java

@Override

public void surfaceCreated(SurfaceHolder holder) {

Canvas canvas = holder.lockCanvas();

if (canvas != null) {

Paint paint = new Paint();

paint.setColor(Color.RED);

canvas.drawRect(0, 0, getWidth(), getHeight(), paint);

holder.unlockCanvasAndPost(canvas);

}

}

```

5.在子线程中更新Surface

在子线程中更新Surface时,需要通过SurfaceHolder.lockCanvas()方法获取到Canvas对象,更新完毕后调用unlockCanvasAndPost()方法提交。示例代码如下:

```java

private void updateSurfaceInThread() {

new Thread(new Runnable() {

@Override

public void run() {

while (true) {

Canvas canvas = holder.lockCanvas();

if (canvas == null) {

continue;

}

Paint paint = new Paint();

paint.setColor(Color.BLUE);

canvas.drawRect(0, 0, getWidth(), getHeight(), paint);

holder.unlockCanvasAndPost(canvas);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

}

```

6.优化SurfaceView性能

为了获得更好的性能和更平滑的动画效果,我们需要对SurfaceView进行一些优化。例如,在SurfaceView的回调方法中使用ThreadPoolExecutor类来执行耗时操作,或者使用硬件加速等方法来提高绘制效率。另外,我们还可以通过设置SurfaceView的ZOrder来控制它与其他View的叠放顺序,如设置ZOrderOnTop为true可以使得SurfaceView覆盖在其他View之上。

七、案例说明

下面我们来实现一个简单的SurfaceView动画效果,实现圆在SurfaceView中自动移动的功能。

1.创建Circle类

创建一个Circle类,用于存储圆的坐标、半径和颜色等信息,代码如下:

```java

public class Circle {

private float x;

private float y;

private float radius;

private int color;

public Circle(float x, float y, float radius, int color) {

this.x = x;

this.y = y;

this.radius = radius;

this.color = color;

}

public void draw(Canvas canvas) {

Paint paint = new Paint();

paint.setAntiAlias(true);

paint.setColor(color);

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

}

public void move(float dx, float dy) {

this.x += dx;

this.y += dy;

}

// getter and setter

}

```

2.创建MySurfaceView类

创建一个MySurfaceView类,继承自SurfaceView,并实现SurfaceHolder.Callback接口。在MySurfaceView的构造方法中获取SurfaceHolder,并注册SurfaceHolder的Callback。然后在surfaceCreated()回调方法中启动一个动画线程,用于更新圆的位置,并绘制到SurfaceView中。代码如下:

```java

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {

private static final int CIRCLE_RADIUS = 100;

private static final int CIRCLE_COLOR = Color.RED;

private SurfaceHolder holder;

private boolean isDrawing = true;

private Circle circle;

public MySurfaceView(Context context) {

this(context, null);

}

public MySurfaceView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

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

super(context, attrs, defStyleAttr);

init();

}

private void init() {

holder = getHolder();

holder.addCallback(this);

circle = new Circle(getWidth() / 2, getHeight() / 2, CIRCLE_RADIUS, CIRCLE_COLOR);

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

new Thread(new Runnable() {

@Override

public void run() {

float dx = 10;

float dy = 10;

while (isDrawing) {

Canvas canvas = holder.lockCanvas();

if (canvas != null) {

circle.move(dx, dy);

if (circle.getX() + circle.getRadius() >= getWidth() || circle.getX() - circle.getRadius() <= 0) {

dx = -dx;

}

if (circle.getY() + circle.getRadius() >= getHeight() || circle.getY() - circle.getRadius() <= 0) {

dy = -dy;

}

canvas.drawColor(Color.WHITE);

circle.draw(canvas);

holder.unlockCanvasAndPost(canvas);

}

}

}

}).start();

}

@Override

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

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

isDrawing = false;

}

}

```

3.在布局文件中使用MySurfaceView

在布局文件中添加MySurfaceView控件,然后运行应用即可看到一个移动的红色圆。

```xml

android:layout_width="match_parent"

android:layout_height="match_parent" />

```

总结:

以上就是关于Surface、SurfaceView和SurfaceHolder的详细介绍,以及使用方法和案例说明。它们是Android图形和动画开发中非常重要的基础知识,掌握它们有助于我们开发出更加流畅、高效的应用。 如果你喜欢我们三七知识分享网站的文章, 欢迎您分享或收藏知识分享网站文章 欢迎您到我们的网站逛逛喔!https://www.37seo.cn/

点赞(38) 打赏

评论列表 共有 0 条评论

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