2014-09-04 1 views
0

스레드 내에서 SurfaceView에 도형을 그리려고하지만 아무 것도 화면에 렌더링되지 않습니다. 저는 같은 문제를 가진 사람들이 비슷한 질문을 한 적이 있지만 그 답이 하나도 없기 때문에 어떤 경우에 다른 원인을 제시하는 해결책을 찾지 못했습니다.SurfaceView가 비어 있고 아무 것도 렌더링되지 않습니다.

문제를 설명하기 위해 간단한 코드 버전을 만들었습니다. 렌더링은 SurfaceView에서 파생 된 사용자 정의보기를 구현하는 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() 내부에 중단 점을 배치 성공적으로 호출되고 있다고 확인 : 렌더링 스레드의 Runnable 내부 RenderingTestView로 구현됩니다.

은 레이아웃 파일은 다음과 같다 :

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

을 ... 사실에서 원하는 출력을 생성 않습니다 init_view() 내부 setWillNotDraw(false) 전화 :하지만,

<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> 

이 같은 RenderingTestViewonDraw() 재정의 onDraw()에 대한 호출을 생성하기 위해 invalidate()를 기다리지 않고 Runnable 내부에서 렌더링하려고합니다.

+0

당신이하고있는 일과 왜 잘못되었는지를 묘사하기가 어렵습니다. SurfaceView는 다른 뷰와 다르다는 것을 이해하십시오 - View 파트와 Surface 파트가 있습니다. 보기 부분은 레이아웃을위한 투명한 자리 표시 자이므로 무시해야합니다. Surface는 SurfaceHolder API로 Z 순서를 변경하지 않는 한 모든 UI 요소 뒤에 그려지는 완전히 별개의 레이어입니다. 레이아웃을 확인하고보기 부분을 불투명 한 색상으로 지우지 않았는지 확인하십시오. – fadden

+0

내가하고있는 것은 셰이프를 SurfaceView의 캔버스에 렌더링하는 것이다. 문제는 제가 게시 한 정확한 코드가 사실 캔버스 위에 아무것도 그리지 않는다는 것입니다. 어쨌든, 나는 마침내 원인을 발견하고 대답을 게시 할 것입니다. –

답변

1

추가 테스트 후, 나는 문제가 다음 코드로 인해 발생 발견했습니다 :

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

그것은 어떻게 든 Canvas 위에 아무것도 렌더링에서 SurfaceView을 방지 위와 같이 setLayerType()를 호출 밝혀, 어떠한 경우에 SurfaceView 렌더링은 항상 소프트웨어에서 수행되므로 불필요합니다. 처음으로 드로 콜을 테스트 할 때 나는 SurfaceView이 아닌 View이라는 정규형을 사용하고 있었고, 문제의 라인은 이월되었다.

관련 문제