Android 开发view、surfaceview、GLsurfaceview的区别及基于surfaceview的示波器开发
Android画布(View SurfaceView GLsurfaceView)
View:显示视图,内置画布,提供图形绘制函数、触屏事件、按键事件函数等;必须在UI主线程内更新画面,速度较慢。
SurfaceView:基于view视图进行拓展的视图类,更适合2D游戏的开发;是view的子类,类似使用双缓机制,在新的线程中更新画面所以刷新界面速度比view快。
GLSurfaceView:基于SurfaceView视图再次进行拓展的视图类,专用于3D游戏开发的视图;是SurfaceView的子类,openGL专用。
SurfaceView和View的区别为:View的绘图必须在当前UI线程中进行,也就是部分程序需要更新View组件时总要采用新的线程去更新SurfaceView的绘制;但SurfaceView就不会存在这个问题,因为SurfaceView的绘图是由SurfaceHolder来完成的。
对于View组件来说,如果程序需要花费较长的时间来更新绘画,那么主UI线程将会被阻塞,无法响应用户的任何动作;而SurfaceHolder则会启用新的线程去更新SurfaceView的绘制,因此不会阻塞主UI线程。
一般来说,如果Android程序或游戏界面的动画元素较多,而且很多动画元素的移动都需要通过定时器来控制,就可以考虑SurfaceView,而不是View。
所以基于以上,根据不同的时间需求,一般分成两类。
1.被动更新画面的,用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate()。这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。
2.主动更新,比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。所以显然view不合适,需要surfaceView来控制。
一般2D游戏开发使用SurfaceView足够,因为它也是google专们扩展用于2D游戏开发的画布使用普通的游戏画布(Android中2D专用游戏画布)中进行绘制图片,然后在GLSurfaceView(Android中3D游戏专用画布)中渲染图片的对比中发现GLSurfaceView的效率高于SurfaceView的30倍;GLSurfaceView的效率主要是因为机器硬件的GPU加速,现在flash技术也有了GPU加速技术;
基于SurfaceView开发的示波器
程序代码如下:
1、绘制示波器背景颜色及坐标轴
private void drawBack(SurfaceHolder holder)
{
Canvas canvas = holder.lockCanvas();
// 绘制白色背景
canvas.drawColor(Color.WHITE);
paint.setColor(Color.BLACK);
// 绘制坐标轴
canvas.drawLine(X_OFFSET, centerY,
screenWidth, centerY, paint);
canvas.drawLine(X_OFFSET, 40f, X_OFFSET, HEIGHT, paint);
holder.unlockCanvasAndPost(canvas);
holder.lockCanvas(new Rect(0, 0, 0, 0));
holder.unlockCanvasAndPost(canvas);
}
2、利用sin cos函数基于SurfaceView绘制图形
View.OnClickListener listener = source -> {
drawBack(holder);
cx = X_OFFSET;
if (task != null)
{
task.cancel();
}
task = new TimerTask()
{
@Override
public void run()
{
paint.setColor(Color.BLUE);
int cy = source.getId() == R.id.sin ?
centerY - (int)(100 * Math.sin((cx - 5) * 2
* Math.PI / 150))
: centerY - (int)(100 * Math.cos ((cx - 5)
* 2 * Math.PI / 150));
Canvas canvas = holder.lockCanvas(new Rect(cx, cy,
cx + (int)paint.getStrokeWidth(), cy + (int)paint.getStrokeWidth()));
canvas.drawPoint(cx, cy, paint);
cx += 2;
if (cx > screenWidth)
{
task.cancel();
task = null;
}
holder.unlockCanvasAndPost(canvas);
}
};
timer.schedule(task, 0, 10);
};
sin.setOnClickListener(listener);
cos.setOnClickListener(listener);
3、基于SurfaceHolder控制线程来更新绘制图形
holder.addCallback(new SurfaceHolder.Callback()
{
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
drawBack(holder);
}
@Override
public void surfaceCreated(SurfaceHolder myHolder)
{
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
timer.cancel();
}
});
4、项目布局代码
<?xml version="1.0" encoding="utf-8"?><LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/sin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sin" />
<Button
android:id="@+id/cos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cos" />
</LinearLayout>
<SurfaceView
android:id="@+id/show"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" />
`
项目运行截图:
示波器坐标轴的绘制:
示波器正弦函数的绘制:
示波器余弦函数的绘制:
参考链接: view、surfaceview、GLsurfaceview的区别和应用场景.
Android–SurfaceView使用详解
项目地址:Android基于SurfaceView的示波器正余弦函数开发
作者:王集湧 福建师范大学 数学与信息学院
日期:2020年12月27日
原文链接:https://blog.csdn.net/Zichang818/article/details/111827414