Search code examples
javaandroidandroid-recyclerviewsurfaceview

Android RecyclerView fails to render a SurfaceView


can a SurfaceView be rendered inside a RecyclerView

EDIT: even this fails to render inside of a RecyclerView: https://github.com/android/ndk-samples/tree/master/hello-gl2

EDIT2: https://github.com/mgood7123/RecyclerViewSurfaceViewGrid minimal example demonstrating the issue

    // public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback2 {
    // class GL2JNIView extends GLSurfaceView {
    GL2JNIView mView;
    public ViewGroup onViewRequest(Context mContext) {
        if (context == null) context = mContext;
        mView = new GL2JNIView(context);
        RelativeLayout rel = new RelativeLayout(context);
        rel.addView(mView);
        mView.onResume();
        return rel;
    }
    public ViewGroup onViewRequest_(Context mContext) {} // old openGL Cube

what i am trying to do is make a Grid of SurfaceView's

@Keep
public class NativeView {
    String TAG = "EglSample";
    public static native void nativeOnStart();
    public static native void nativeOnResume();
    public static native void nativeOnPause();
    public static native void nativeOnStop();

    // this is part of graphics manager
    public native void nativeSetSurface(Surface surface);

    View surfaceView = null;
    SurfaceHolderCallback surfaceHolderCallback = null;

    public NativeView(Context context) {
        System.loadLibrary("nativeegl");
        surfaceHolderCallback = new SurfaceHolderCallback();
        surfaceView = new View(surfaceHolderCallback, context);
    }

    class View extends SurfaceView {
        public View(SurfaceHolder.Callback callback, Context context) {
            super(context);
            getHolder().addCallback(callback);
        }

        public View(SurfaceHolder.Callback callback, Context context, AttributeSet attrs) {
            super(context, attrs);
            getHolder().addCallback(callback);
        }

        public View(SurfaceHolder.Callback callback, Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            getHolder().addCallback(callback);
        }

        public View(SurfaceHolder.Callback callback, Context context, AttributeSet attrs, int defStyle, int defStyleRes) {
            super(context, attrs, defStyle, defStyleRes);
            getHolder().addCallback(callback);
        }
    }

    class SurfaceHolderCallback implements SurfaceHolder.Callback {
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
            nativeSetSurface(holder.getSurface());
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            nativeSetSurface(null);
        }
    }
}
    public ViewGroup onViewRequest(Context mContext) {
        if (context == null) context = mContext;

        if (n == null) n = new NativeView(context);
        Log.i(n.TAG, "onViewRequest(Activity, Context)");
        // build layout
        RelativeLayout rel = new RelativeLayout(context);
        rel.addView(n.surfaceView);
        n.surfaceView.setOnClickListener(new MyListener());
        // set text
        TextView text = new TextView(context);
        text.setText("Hello World! Try clicking the screen");
        text.setTextSize(60f);
        text.setTextColor(Color.WHITE);
        rel.addView(text);
        Log.i(n.TAG, "onCreate()");
        // build layout
        NativeView.nativeOnStart();
        NativeView.nativeOnResume();
        return rel;
    }

full:

https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/vstdemoopengladdonscube/src/main/java/vst/demo/opengl/addons/cube/main.java

https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/vstdemoopengladdonscube/src/main/java/vst/demo/opengl/addons/cube/NativeView.java

as it renders corrupted in a recycler view (text but no surface view) (you can barely make out the white text but the fact that it is there means the view heirarchy IS being drawn)

corrupted

(set USE_RECYCLER_VIEW = true)

https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/VstManager/src/main/java/vst/manager/VstGrid.java#L29

    Boolean USE_RECYCLER_VIEW = false;
    public LinearLayout getView() {
        // this assumes the first available "*\.addons\.*" package
        if (!USE_RECYCLER_VIEW) {
            VST pkg = mVstMan.loadPackage(mActivity, mVstMan.getPackages(mActivity)[0].packageName, false);
            VST.CLASS vstClass = mVstMan.loadClass(pkg, "main");
            Object vstClassInstance = mVstMan.newInstance(vstClass, "main");
            // android.widget.RelativeLayout cannot be cast to android.widget.LinearLayout
            LinearLayout x = new LinearLayout(mActivity);
            x.addView((ViewGroup) mVstMan.invokeMethod(
                    vstClass, vstClassInstance,
                    "onViewRequest", Context.class,
                    pkg.activityApplicationContext
                    )
            );
            return x;
        } else {
            if (recyclerViewMain == null)
                recyclerViewMain = (LinearLayout) LayoutInflater.from(mActivity.getApplicationContext())
                        .inflate(R.layout.vst_grid, null, false);
            if (recyclerView == null) {
                recyclerView = recyclerViewMain
                        .findViewById(R.id.VstGrid);

                // use this setting to improve performance if you know that changes
                // in content do not change the layout size of the RecyclerView
                recyclerView.setHasFixedSize(true);
            }
            if (layoutManager == null) {
                // use a linear layout manager
                layoutManager = new GridLayoutManager(mActivity, 1);
                recyclerView.setLayoutManager(layoutManager);
            }
            if (mAdapter == null) {
                // specify an adapter (see also next example)
                mAdapter = new VstGridAdapter(mActivity, mVstMan, mVstUI);
                recyclerView.setAdapter(mAdapter);
            }
            mAdapter.update();
            return recyclerViewMain;
        }
    }

https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/VstManager/src/main/java/vst/manager/VstGridAdapter.java#L86

    // Create new views (invoked by the layout manager)
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        VST pkg = mVstMan.loadPackage(mActivity, mVstMan.getPackages(mActivity)[0].packageName, false);
        VST.CLASS vstClass = mVstMan.loadClass(pkg, "main");
        Object vstClassInstance = mVstMan.newInstance(vstClass, "main");
        // android.widget.RelativeLayout cannot be cast to android.widget.LinearLayout
        LinearLayout x = new LinearLayout(mActivity);
        x.addView((ViewGroup) mVstMan.invokeMethod(
                        vstClass, vstClassInstance,
                        "onViewRequest", Context.class,
                        pkg.activityApplicationContext
                )
        );
        return new MyViewHolder(x);
    }

https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/vstdemoopengladdonscube/src/main/cpp/RotatingSquares/jniapi.cpp

https://github.com/mgood7123/VSTDEMO/blob/0f5e7063d9ebef5ae5a05f128d548eec712b741f/vstdemoopengladdonscube/src/main/cpp/RotatingSquares/renderer.cpp#L153

meanwhile it renders perfectly fine if NOT in a recycler view (leave USE_RECYCLER_VIEW as false)

not corrupted

why?


Solution

  • apparently in order to get it to display i needed to give the view fixed size layout paramaters: mView.setLayoutParams(new ViewGroup.LayoutParams(500, 500));