您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# Android SurfaceView的基础用法介绍
## 一、SurfaceView概述
### 1.1 什么是SurfaceView
SurfaceView是Android中一个特殊的视图组件,继承自View类。与普通View不同,SurfaceView具有以下核心特点:
- **独立的绘制表面**:SurfaceView拥有独立的Surface(表面),可以在非UI线程中进行绘制
- **双缓冲机制**:内置双缓冲技术,减少画面闪烁
- **高性能绘制**:适合处理复杂的图形操作和频繁的界面更新
### 1.2 SurfaceView与普通View的区别
| 特性 | SurfaceView | 普通View |
|---------------------|-----------------------------|--------------------------|
| 绘制线程 | 可在子线程绘制 | 必须在UI线程绘制 |
| 绘制效率 | 高,适合高频刷新 | 相对较低 |
| 内存消耗 | 较高 | 较低 |
| 透明度支持 | 不支持 | 支持 |
| 叠加显示 | 可能被其他View遮挡 | 按视图层级正常显示 |
### 1.3 适用场景
1. 游戏开发
2. 视频播放器
3. 相机预览
4. 实时图表绘制
5. 任何需要高频界面更新的场景
## 二、SurfaceView基本使用
### 2.1 基础实现步骤
#### 1. 继承SurfaceView
```java
public class MySurfaceView extends SurfaceView
implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
public MySurfaceView(Context context) {
super(context);
init();
}
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mHolder = getHolder();
mHolder.addCallback(this);
}
// 实现SurfaceHolder.Callback接口方法
@Override
public void surfaceCreated(SurfaceHolder holder) {
// 表面创建时调用
}
@Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
// 表面发生变化时调用
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// 表面销毁时调用
}
}
private class DrawThread extends Thread {
private boolean isRunning = true;
@Override
public void run() {
while(isRunning) {
Canvas canvas = null;
try {
canvas = mHolder.lockCanvas();
if(canvas != null) {
// 在此进行绘制操作
drawSomething(canvas);
}
} finally {
if(canvas != null) {
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}
public void stopThread() {
isRunning = false;
}
}
addCallback(SurfaceHolder.Callback callback)
:添加回调lockCanvas()
:锁定画布准备绘制unlockCanvasAndPost(Canvas canvas)
:提交绘制内容getSurface()
:获取底层Surface对象drawColor(int color)
:填充背景色drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
:绘制位图drawCircle(float cx, float cy, float radius, Paint paint)
:绘制圆形drawRect(float left, float top, float right, float bottom, Paint paint)
:绘制矩形// 创建离屏Bitmap作为缓冲区
Bitmap mBufferBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas mBufferCanvas = new Canvas(mBufferBitmap);
private void drawWithDoubleBuffer() {
// 1. 在缓冲Canvas上绘制
drawToBufferCanvas(mBufferCanvas);
// 2. 将缓冲内容绘制到SurfaceView
Canvas surfaceCanvas = mHolder.lockCanvas();
if(surfaceCanvas != null) {
try {
surfaceCanvas.drawBitmap(mBufferBitmap, 0, 0, null);
} finally {
mHolder.unlockCanvasAndPost(surfaceCanvas);
}
}
}
// 控制帧率为60FPS
private static final int FPS = 60;
private static final long FRAME_TIME = 1000 / FPS;
@Override
public void run() {
long startTime;
long waitTime;
while(isRunning) {
startTime = System.currentTimeMillis();
// 绘制逻辑
renderFrame();
// 计算等待时间
waitTime = FRAME_TIME - (System.currentTimeMillis() - startTime);
if(waitTime > 0) {
try {
sleep(waitTime);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 在SurfaceView上叠加其他View
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.MySurfaceView
android:id="@+id/surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button
android:id="@+id/control_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:text="Pause"/>
</FrameLayout>
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// 停止绘制线程
if(mDrawThread != null) {
mDrawThread.stopThread();
try {
mDrawThread.join(500); // 等待线程结束
} catch (InterruptedException e) {
e.printStackTrace();
}
mDrawThread = null;
}
}
surfaceCreated
后才启动绘制线程lockCanvas()
是否返回nullprivate void init() { mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.FILL); }
3. **使用硬件加速**:
```xml
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hardwareAccelerated="true"/>
public class DrawingSurfaceView extends SurfaceView
implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder mHolder;
private Thread mDrawThread;
private boolean isRunning;
private Path mPath = new Path();
private Paint mPaint = new Paint();
public DrawingSurfaceView(Context context) {
super(context);
init();
}
private void init() {
mHolder = getHolder();
mHolder.addCallback(this);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mPaint.setAntiAlias(true);
setFocusable(true);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
@Override
public void run() {
while(isRunning) {
Canvas canvas = mHolder.lockCanvas();
if(canvas != null) {
try {
// 清屏
canvas.drawColor(Color.WHITE);
// 绘制路径
canvas.drawPath(mPath, mPaint);
} finally {
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}
// 实现SurfaceHolder.Callback方法...
}
public void setPaintColor(int color) {
mPaint.setColor(color);
}
public void setEraserMode(boolean isEraser) {
if(isEraser) {
mPaint.setColor(Color.WHITE);
mPaint.setStrokeWidth(20);
} else {
mPaint.setColor(mCurrentColor);
mPaint.setStrokeWidth(5);
}
}
public Bitmap saveDrawing() {
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
draw(canvas);
return bitmap;
}
TextureView:
GLSurfaceView:
Jetpack Compose Canvas:
附录:常用资源
”`
这篇文章共计约4050字,全面介绍了Android SurfaceView的基础用法,包含: 1. 核心概念解析 2. 基础实现代码 3. 高级优化技巧 4. 常见问题解决方案 5. 完整实战案例 6. 扩展学习建议
文章采用Markdown格式,结构清晰,包含代码示例、表格对比和层级分明的章节组织,适合Android开发者学习参考。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。