javascript - react native Android : Resizing native UI Component causes black out

标签 javascript java android react-native

关于在 Android 上使用 GLSurfaceView 和 React Native,我遇到了一个非常奇怪的问题。

我创建了一个自定义 OpenGL 渲染器,我想将其用作更大的 React Native View 中的一个组件。问题是,当我将 JS 端的组件调整为我希望屏幕其余部分变黑的大小时。

enter image description here

这是创建该 View 的 React Native 代码:

    public render() {
       return (
            <View style={{ backgroundColor: '#ffffff' }}>
                <Text>Hello World!</Text>
                <ImageBlendView style={{ height: 50 }} boxColour="#f442df" />
            </View>
        );
    }

ImageBlendView 是我按照 RN 网站上的说明制作的 react-native UI 组件 here ,这就是创建红色和紫色矩形的原因。它只是一个非常基本的 Opengl 渲染器,它使用从 JS 传入的颜色和红色透明颜色绘制一个矩形。我在其上方添加了一个文本字段并将组件的大小调整为 50 高度。

我不明白为什么 ImageBlendView 组件被黑色包围。

清晰的颜色是红色,所以我知道它不是我的渲染器清除不应该的像素。但是,它似乎确实与我的渲染器类有关,因为当我在 GLSurfaceView 类中注释掉我将其设置为渲染器的行时,正常的白色背景返回并且组件上方的文本可见。

// setRenderer(new OpenGLRenderer(_context, colour));

自定义 UI 组件遵循与教程中相同的结构,但我将逐步介绍它以确保完整。

ImageBlendView 被添加到一个包中并 bundle 在 View 管理器列表中:

public class OTSNativePackage implements ReactPackage {

    @Nonnull
    @Override
    public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {
        List<NativeModule> nativeModules = new ArrayList<>();
        return nativeModules;
    }

    @Nonnull
    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Arrays.<ViewManager>asList(new ImageBlendView());
    }
}

ImageBlendView.java 然后扩展 SimpleViewManager,创建一个扩展 GLSurfaceView 的 OpenGLView 实例

public class ImageBlendView extends SimpleViewManager<OpenGLView> {

    public static final String REACT_CLASS = "ImageBlendView";
    private static OpenGLView _openGLView;

    @Nonnull
    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @Nonnull
    @Override
    protected OpenGLView createViewInstance(@Nonnull ThemedReactContext reactContext) {
        _openGLView = new OpenGLView(reactContext);
        return _openGLView;
    }


    @ReactProp(name = "boxColour")
    public void setBoxColour(OpenGLView view, String color) {
        _openGLView.init(color);
    }
}

OpenGLView.java

public class OpenGLView extends GLSurfaceView {
    private Context _context;
    public OpenGLView(Context context) {
        super(context);
        _context = context;
    }

    public OpenGLView(Context context, AttributeSet attrs) {
        super(context, attrs);
        _context = context;
    }

    public void init(String colour){
        setEGLContextClientVersion(2);
        setPreserveEGLContextOnPause(true);

        // If I disable the following line the black goes away
        setRenderer(new OpenGLRenderer(_context, colour)); 
    }
}

请注意,在上面的类中,我可以在此处禁用 setRenderer 行,黑色消失。

我的渲染器在 OpenGLRenderer.java 中

public class OpenGLRenderer implements GLSurfaceView.Renderer {
    private Context _context;
    private FloatBuffer vertexBuffer;
    private ShortBuffer drawListBuffer;
    private int positionHandle, program, colorHandle;
    static final int COORDS_PER_VERTEX = 3;

    static float squareCoords[] = {
        -0.5f,  0.5f, 0.0f,   // top left
        -0.5f, -0.5f, 0.0f,   // bottom left
         0.5f, -0.5f, 0.0f,   // bottom right
         0.5f,  0.5f, 0.0f }; // top right

    private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices


    float color[] = {0.5f, 0.5f, 0.55f, 1.0f};
    private int vertexCount;
    private int vertexStride; // 4 bytes per vertex

    public OpenGLRenderer(Context context, String colorStr){
        super();
        _context = context;
        color = new float[]{(float)Integer.valueOf( colorStr.substring( 1, 3 ), 16 ) / 256.0f,
                        (float)Integer.valueOf( colorStr.substring( 3, 5 ), 16 ) / 256.0f,
                        (float)Integer.valueOf( colorStr.substring( 5, 7 ), 16 ) / 256.0f, 1.0f};
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glClearColor(1f,0f,0f,1f);

        ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareCoords);
        vertexBuffer.position(0);

        // initialize byte buffer for the draw list
        ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);

        vertexCount = squareCoords.length / COORDS_PER_VERTEX;
        vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

        GLES20.glEnable(GLES20.GL_SCISSOR_TEST);

        compileShaders();
        sendData();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
        GLES20.glScissor(0,0, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

        GLES20.glEnableVertexAttribArray(positionHandle);

        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

        GLES20.glDisableVertexAttribArray(positionHandle);
    }

    private void sendData(){
        positionHandle = GLES20.glGetAttribLocation(program, "position");
        GLES20.glEnableVertexAttribArray(positionHandle);

        GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
                             GLES20.GL_FLOAT, false,
                             vertexStride, vertexBuffer);

        colorHandle = GLES20.glGetUniformLocation(program, "vColor");

        GLES20.glUniform4fv(colorHandle, 1, color, 0);
    }

    private void compileShaders() {

        int vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
        GLES20.glShaderSource(vertexShader, getShaderSource(R.raw.vertex_shader));

        int fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
        GLES20.glShaderSource(fragmentShader, getShaderSource(R.raw.fragment_shader));

        GLES20.glCompileShader(vertexShader);
        GLES20.glCompileShader(fragmentShader);

        program = GLES20.glCreateProgram();
        GLES20.glAttachShader(program, vertexShader);
        GLES20.glAttachShader(program, fragmentShader);

        GLES20.glLinkProgram(program);
        GLES20.glUseProgram(program);
    }

    private String getShaderSource(int input){
        StringBuilder total = new StringBuilder();
        try{
            InputStream stream =
                _context.getResources().openRawResource(input);

            BufferedReader r = new BufferedReader(new InputStreamReader(stream));
            total = new StringBuilder();
            for (String line; (line = r.readLine()) != null; ) {
                total.append(line).append('\n');
            }
        } catch (IOException e){
            System.out.println(e.getMessage());
        }

        return total.toString();
    }
}

我最近尝试的是调用 GLES20.glScissor(0,0, width, height);在 onSurfaceChanged 方法中。我希望通过剪裁到组件的大小和高度,它不会影响其余像素,但它变得非常清楚,这不是 OpenGL 的问题,而是设置的问题。

最佳答案

终于找到解决办法了。我只是将 JS 代码更改为:

    public render() {
        console.log('***', ImageBlend);
        return (
            <View style={{ backgroundColor: '#ffffff' }}>
                <Text>Hello Nick!</Text>
                <View style={{ height: 50, overflow: 'hidden' }}>
                    <ImageBlendView
                        style={{ height: 50 }}
                        boxColour="#f442df"
                    />
                </View>
            </View>
        );
    }

关于javascript - react native Android : Resizing native UI Component causes black out,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56728120/

相关文章:

javascript - Computed.alias 不更新绑定(bind)属性

java - R.字符串比较

java - 如何正确转义 lucene 查询?

Android 自定义组件不工作

javascript - 确保变量是数组

javascript - 如何检查用户是否有 Google 帐户。

javascript - 带有 Angular 指令的 TreeView

java - 使用 Android 应用程序将文件上传到我的 Google API 项目

java - Android - Preference OnPreferenceClick 永远不会被调用

java - 如何获取android.jar的源代码