Java SurfaceView显示为空,未渲染任何内容
我试图从一个线程中在SurfaceView上绘制一些形状,但是没有任何东西被渲染到屏幕上。我看过有相同问题的人提出的类似问题,但没有一个答案能让我找到解决方案,在我的特殊情况下,提出了不同的原因 我已经创建了一个简化版本的代码来演示这个问题。渲染由RenderingTestView类处理,该类实现从SurfaceView派生的自定义视图。渲染线程实现为可运行的内部RenderingTestView:Java SurfaceView显示为空,未渲染任何内容,java,android,multithreading,graphics,surfaceview,Java,Android,Multithreading,Graphics,Surfaceview,我试图从一个线程中在SurfaceView上绘制一些形状,但是没有任何东西被渲染到屏幕上。我看过有相同问题的人提出的类似问题,但没有一个答案能让我找到解决方案,在我的特殊情况下,提出了不同的原因 我已经创建了一个简化版本的代码来演示这个问题。渲染由RenderingTestView类处理,该类实现从SurfaceView派生的自定义视图。渲染线程实现为可运行的内部RenderingTestView: package com.example.renderingtest.app; import a
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);
}
}
在Draw()
中放置一个断点可以确认调用成功
布局文件如下所示:
<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>
@Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Draw(canvas);
}
。。。调用
setWillNotDraw(false)
insideinit_view()
实际上会生成所需的输出,但我希望从Runnable内部进行渲染,而不是等待invalidate()生成对onDraw()
的调用在进一步测试后,我发现问题是由以下代码引起的:
if (Build.VERSION.SDK_INT >= 11)
setLayerType(android.view.View.LAYER_TYPE_SOFTWARE, null);
事实证明,如上所述调用
setLayerType()
会以某种方式阻止SurfaceView
在Canvas
上渲染任何内容,而且在任何情况下都是不必要的,因为SurfaceView
渲染始终在软件中执行。第一次测试draw调用时,我使用的是常规的视图
,而不是SurfaceView
,因此产生了一些问题。很难想象你在做什么以及为什么出错。请务必了解SurfaceView与其他视图不同——它有一个视图部分和一个曲面部分。视图零件是用于布局的透明占位符,应忽略。曲面是在所有UI元素后面绘制的完全独立的层(除非使用SurfaceHolder API更改Z顺序)。检查布局,确保没有将视图部分清除为不透明颜色。我正在做的是将形状渲染到SurfaceView的画布上。问题是,我发布的确切代码没有在画布上绘制任何东西,而事实上它应该这样做。无论如何,我终于找到了原因,并将公布答案。