SurfaceView显示为空,没有被渲染 [英] SurfaceView appears empty, nothing being rendered

查看:573
本文介绍了SurfaceView显示为空,没有被渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从一个线程中绘制一些形状拖到一个SurfaceView,但没有被渲染到屏幕上。我已经用有同样的问题让人看了类似的问题,但没有答案的,导致我的解决方案,这在我的具体情况不同的原因。

I'm trying to draw some shapes onto a SurfaceView from within a thread, but nothing is being rendered to the screen. I've looked at similar questions by people having the same problem, but none of the answers have led me to a solution, suggesting a different cause in my particular case.

我已经建立了我code,以说明问题的简化版本。渲染是由RenderingTestView类,它实现从SurfaceView派生的自定义视图处理。渲染线程是作为一个Runnable内RenderingTestView:

I've created a simplified version of my code to demonstrate the problem. Rendering is handled by the RenderingTestView class, which implements a custom view derived from SurfaceView. The rendering thread is implemented as a Runnable inside RenderingTestView:

package com.example.renderingtest.app;

import android.content.Context;
import android.graphics.*;
import android.os.Build;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class RenderingTestView extends SurfaceView {
    private SurfaceHolder holder;
    private Paint paint;
    private boolean surfaceCreated = false;
    private Thread videoThread;

    public RenderingTestView(Context context) {
        super(context);
        init_view(context);
    }

    public RenderingTestView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init_view(context);
    }

    public RenderingTestView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init_view(context);
    }

    private void init_view(Context context)
    {
        if (Build.VERSION.SDK_INT >= 11)
            setLayerType(android.view.View.LAYER_TYPE_SOFTWARE, null);

        paint = new Paint();
        paint.setColor(Color.RED);

        holder = getHolder();

        holder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                surfaceCreated = true;

                videoThread = new Thread(videoRunnable);
                videoThread.start();
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                // do nothing
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                surfaceCreated = false;
            }
        });
    }

    private Runnable videoRunnable = new Runnable() {
        @Override
        public void run() {
            Thread.currentThread().setPriority(Thread.NORM_PRIORITY);

            while (true) {
                if (!surfaceCreated || !holder.getSurface().isValid())
                    continue;

                Canvas c = holder.lockCanvas(null);
                try {
                    synchronized (holder) {
                        if (c != null)
                            Draw(c);
                    }
                }
                finally {
                    if (c != null)
                        holder.unlockCanvasAndPost(c);
                }
            }
        }
    };

    protected void Draw(Canvas canvas)
    {
        canvas.drawCircle(0, 0, 100, paint);
    }
}

里面放置断点绘制()确认它被成功调用。

布局文件看起来是这样的:

The layout file looks like this:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="com.example.renderingtest.app.RenderingTest" android:background="#000000">

    <com.example.renderingtest.app.RenderingTest
            android:id="@+id/renderingTestView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true" android:layout_alignParentTop="true"/>

</RelativeLayout>

重写的onDraw() RenderingTestView ,就像这样:

@Override
public void onDraw(Canvas canvas)
{
     super.onDraw(canvas);
     Draw(canvas);
}

......,并呼吁 setWillNotDraw(假) init_view()事实上确实产生所需的输出,但我想从里面的Runnable来呈现,而不是等待无效()来产生一个呼叫的onDraw()

... and calling setWillNotDraw(false) inside init_view() does in fact produce the desired output, but I want to render from inside the Runnable rather than wait for invalidate() to produce a call to onDraw().

推荐答案

进一步测试后,我发现这个问题是由以下code引起的:

After further testing, I've discovered the problem is caused by the following code:

if (Build.VERSION.SDK_INT >= 11)
    setLayerType(android.view.View.LAYER_TYPE_SOFTWARE, null);

原来调用 setLayerType()如上莫名其妙prevents SurfaceView 从渲染任何东西到画布,并在任何情况下不必要的,因为 SurfaceView 渲染总是在软件中执行。当第一次测试我的绘制调用我使用的是普通的查看而非 SurfaceView ,以及违规结转线从。

It turns out calling setLayerType() as above somehow prevents SurfaceView from rendering anything onto the Canvas, and is in any case unnecessary since SurfaceView rendering is always performed in software. When first testing my draw calls I was using a regular View rather than a SurfaceView, and the offending lines were carried over from that.

这篇关于SurfaceView显示为空,没有被渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆