如何向渲染器添加按钮?

时间:2018-02-05 14:39:11

标签: android opengl-es-2.0

我在android studio中做了一个高度图。它有一个Main活动,如下所示:

public class MainActivity extends AppCompatActivity {
private GLSurfaceView glSurfaceView;
private boolean rendererSet = false;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    glSurfaceView = new GLSurfaceView(this);

    final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

    final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();

    final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000
            || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
            && (Build.FINGERPRINT.startsWith("generic")
            || Build.FINGERPRINT.startsWith("unknown")
            || Build.MODEL.contains("google_sdk")
            || Build.MODEL.contains("Emulator")
            || Build.MODEL.contains("Android SDK built for x86")));
    final FirstOpenGLProjectRenderer firstOpenGLProjectRenderer = new FirstOpenGLProjectRenderer(this);
    if(!firstOpenGLProjectRenderer.getError()) {
        if (supportsEs2) {
            glSurfaceView.setEGLContextClientVersion(2);
            glSurfaceView.setRenderer(firstOpenGLProjectRenderer);
            rendererSet = true;
        } else {
            Toast.makeText(this, "this device does not support OpenGL ES 2.0", Toast.LENGTH_LONG).show();
            return;
        }

        setContentView(glSurfaceView);

    }else{
     setContentView(R.layout.error);
    }
}

@Override
protected void onPause(){
    super.onPause();
    if(rendererSet) {glSurfaceView.onPause();}
}

@Override
protected void onResume(){
    super.onResume();

    if(rendererSet){
        glSurfaceView.onResume();
    }
}
public static void main(String []args){}
}

我也有渲染器类,如下所示:

public class FirstOpenGLProjectRenderer implements Renderer {

private float min;
private float max;
private float ratio;
private FloatBuffer vertexPositions;
private FloatBuffer vertexColors;

private int alpha = 1000;

private float[] positions;
private float[] colors;

private Context context;
private boolean error;

private ArrayList<Float> nodePositions;

private static final int BYTES_PER_FLOAT = 4;
private int program;
private static final String A_COLOR = "a_Color";
private int aColorLocation;
private static final String A_POSITION = "a_Position";
private int aPositionLocation;
private final int POSITION_COMPONENT_COUNT = 3; //x,y,z
private ArrayList<Float> triangleZList;

public FirstOpenGLProjectRenderer(Context context) {

    this.context = context;
    ArcGridReader arcGridReader = new ArcGridReader(context);
    this.nodePositions = arcGridReader.getNodePositions();
    this.triangleZList = arcGridReader.getTriangleZList();

    error = arcGridReader.getError();
    if(!error) {
        calc();
    }

}

public boolean calc(){
        positions = new float[nodePositions.size()];
        //Todo: färgerna
        colors = new float[triangleZList.size() * 3];

        min = Collections.min(triangleZList) / alpha;
        max = Collections.max(triangleZList) / alpha;
        ratio = (200 / (max - min));

        int i = 0;
        for (Float test : nodePositions) {
            positions[i] = test / alpha;
            i++;
        }
        double amount = (max/3)*alpha;
        i = 0;
        for (Float test : triangleZList) {

            if(test<=0){
                setColors(test,i,0);
                i=i+3;
            }

            if(test>0 && test<=amount){
                setColors(test,i,10);
                i=i+3;
            }
            if(test>amount && test<=(2*amount)){
                setColors(test,i,20);
                i=i+3;
            }
            if(test>(2*amount) && test<=(3*amount)){
                setColors(test,i,30);
                i=i+3;
            }
        }
        vertexPositions = ByteBuffer
                .allocateDirect(positions.length * BYTES_PER_FLOAT)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        vertexPositions.put(positions);

        vertexColors = ByteBuffer
                .allocateDirect(colors.length * BYTES_PER_FLOAT)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        vertexColors.put(colors);

    return  true;

}

@Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    GLES20.glEnable(GLES20.GL_CULL_FACE);
    GLES20.glEnable(GLES20.GL_DEPTH_TEST);

    String vertexShaderSource = TextResourceReader
            .readTextFileFromResource(context, R.raw.vertex_shader);

    String fragmentShaderSource = TextResourceReader
            .readTextFileFromResource(context, R.raw.fragment_shader);

    int vertexShader = ShaderHelper.compileVertexShader(vertexShaderSource);
    int fragmentShader = ShaderHelper.compileFragmentShader(fragmentShaderSource);


    program = ShaderHelper.linkProgram(vertexShader, fragmentShader);

    if (LoggerConfig.ON) {
        ShaderHelper.validateProgram(program);
    }
    glUseProgram(program);

    aColorLocation = glGetAttribLocation(program, A_COLOR);
    aPositionLocation = glGetAttribLocation(program, A_POSITION);
}

@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
    glViewport(0, 0, width, height);

}

@Override
public void onDrawFrame(GL10 glUnused) {
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

    glUseProgram(program);

    vertexPositions.position(0);
    glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT, false, 0, vertexPositions);
    glEnableVertexAttribArray(aPositionLocation);

    vertexColors.position(0);
    glVertexAttribPointer(aColorLocation, POSITION_COMPONENT_COUNT, GL_FLOAT, false, 0, vertexColors);
    glEnableVertexAttribArray(aColorLocation);

    glDrawArrays(GL_TRIANGLES, 0, positions.length);

}


public void setColors (Float test, int i,int number){

    switch (number){

        case 0:

            colors[i] = 0*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            colors[i] = 0*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            colors[i] = 1*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            break;

        case 10:
            colors[i] = 0*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            colors[i] = 1*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            colors[i] = 0*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            break;

        case 20:

            colors[i] = 1*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            colors[i] = 1*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            colors[i] = 0*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            break;

        case 30:

            colors[i] = 1*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            colors[i] = 0*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            colors[i] = 0*(((test - min) / alpha) * ratio + 20) / 255f;
            i++;
            break;
    }
}

public boolean getError(){
    return error;
}
}

所以现在我想在两个按钮的帮助下添加缩放功能。我知道缩放功能的代码,但我坚持使用按钮的实现。制作按钮并触及按钮的最佳/最简单方法是什么?我只考虑过一种方法,即在主要活动中制作一个片段,有更好的方法吗?

我已经搜索过,但没有想到什么。也许我缺少一些关键词,因为我不是Android Studio中的常用用户。干杯! :)

3 个答案:

答案 0 :(得分:0)

最简单的方法是为您的UI(按钮,文本,编辑等)使用单独的图层,并将其放在GLSurfaceView上方。在xml中定义布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    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">

    <GLSurfaceView
        android:id="@+id/gl_surface_view"
        android:background="#ff0000"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/btn_zoom_in"
            android:text="ZoomIn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <Button
            android:id="@+id/btn_zoom_out"
            android:text="ZoomOut"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

</FrameLayout>

然后让您的glSurfaceView参与活动并处理按钮点击次数:

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity);
    glSurfaceView = new GLSurfaceView(this);

    findViewById(R.id.btn_zoom_in).setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            //handle zoom in
        }
    });

    findViewById(R.id.btn_zoom_out).setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            //handle zoom out
        }
    });

    //...
}

就是这样。

值得一提的是另一种更为复杂的方式:在OpenGL中完全绘制UI并截取GL Surface中的触摸事件:

class Surface extends GLSurfaceView{

    public Surface(Context context) {
        super(context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }
}

答案 1 :(得分:0)

我找到了更适合我的东西,我刚刚在mainactivity中添加了以下代码:

       ...

       setContentView(glSurfaceView);

        LinearLayout ll = new LinearLayout(this);

        Button zoomIn = new Button(this);
        zoomIn.setText("zoomIn");

        Button zoomOut = new Button(this);
        zoomOut.setText("zoomOut");

        ll.addView(zoomIn);
        ll.addView(zoomOut);

        this.addContentView(ll,new 
        ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, 
        ViewGroup.LayoutParams.FILL_PARENT));

        ...

其中this.addContentView是其中的一个关键部分。

答案 2 :(得分:-1)

  1. 设计xml布局。是的,按钮,铃铛和口哨声。 ConstraintLayout会很好
  2. LayoutInflater inflater = getLayoutInflater();
  3. getWindow()。addContentView(inflater.inflate(R.layout.your_xml_layout,null),新的ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
  4. 向按钮等添加事件
  5. 您完成了!现在,您可以在GLSurfaceView之上拥有一个设计完美的UI!