Android 开发view、surfaceview、GLsurfaceview的区别及基于surfaceview的示波器开发

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

猜你喜欢

转载自blog.csdn.net/fjnu_se/article/details/112154581
今日推荐