SurfaceView looks empty, nothing is displayed

I am trying to draw some shapes on a SurfaceView from a stream, but nothing is displayed on the screen. I considered similar questions in people having the same problem, but none of the answers led me to a solution, suggesting a different reason in my particular case.

I created a simplified version of my code to demonstrate this problem. Rendering is handled by the RenderingTestView class, which implements a custom view obtained from SurfaceView. The rendering stream is implemented as Runnable inside the 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); } } 

Placing a breakpoint inside Draw() confirms that it was successfully called.

The layout file is as follows:

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

Overriding onDraw() in a RenderingTestView , for example:

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

... and calling setWillNotDraw(false) inside init_view() does produce the desired result, but I want to render from Runnable and not wait for invalidate () to call onDraw() .

0
source share
1 answer

After further testing, I found that the problem was caused by the following code:

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

It turns out that the call to setLayerType() , as described above, somehow prevents the SurfaceView from rendering anything on the Canvas and is not needed in any case, since SurfaceView rendering is always performed in the software. When I first tested my call appeals, I used a regular View , not a SurfaceView , and the lines were SurfaceView from it in violation.

+1
source

Source: https://habr.com/ru/post/1236067/


All Articles