我想從一個線程內將一些圖形繪製到SurfaceView上,但是沒有任何東西正在呈現給屏幕。我曾經看過類似的問題,但有同樣的問題,但沒有一個答案讓我找到了解決方案,這表明我的具體情況有其他原因。SurfaceView顯示爲空,沒有顯示任何東西
我創建了一個簡化版本的代碼來演示問題。渲染由RenderingTestView類處理,該類實現了從SurfaceView派生的自定義視圖。渲染線程實現爲一個Runnable內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);
}
}
放置一個斷點內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>
重寫onDraw()
在RenderingTestView
,像這樣:
@Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Draw(canvas);
}
...並呼籲setWillNotDraw(false)
內init_view()
事實上確實產生所需的輸出,但我想從Runnable內部進行渲染,而不是等待invalidate()調用onDraw()
。
很難描繪你在做什麼以及爲什麼會出錯。理解SurfaceView與其他Views不同 - 它具有View部分和Surface部分。視圖部分是一個用於佈局目的的透明佔位符,應該被忽略。 Surface是在所有UI元素後面繪製的完全獨立的圖層(除非使用SurfaceHolder API更改Z順序)。檢查你的佈局,並確保你沒有將視圖部分清除爲不透明的顏色。 – fadden 2014-09-04 15:38:43
我正在做的是將圖形渲染到SurfaceView的畫布上。問題是我發佈的確切代碼並沒有在畫布上繪製任何東西,實際上它應該是這樣。無論如何,我終於找到了原因,並會發布答案。 – 2014-09-04 17:55:41