Home > Software design >  Android custom SurfaceView orientation can't rotate from portrait to landscape
Android custom SurfaceView orientation can't rotate from portrait to landscape

Time:12-27

I'm a new android application engineer. I'm trying to make a vulkan rendering backend demo which use SurfaceView as a View on android Java code. I made the gles rendering backend demo using GLSurfaceView as well. On application code, I use setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) API set activity from default portrait to landscape. But it doesn't work on SurfaceView while it works on GLSurfaceView.

I use renderdoc capture the rendering result, the image is in landscape layout(the same layout as gles backend). I doubt it was's something wrong with some settings on activity or window, but can't figure it out the root cause. Could somebody help what maybe the problem is?

Here is the Java source code.

package com.example.graphicsdebugger;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;

//////////////////////////////////////////////Jerome///////////////////////////////////////////////
import android.view.SurfaceHolder;
import android.view.View;
import android.view.WindowManager;
import android.util.Log;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.TextView;

///////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * An example full-screen activity that shows and hides the system UI (i.e.
 * status bar and navigation/system bar) with user interaction.
 */
public class DemoFullscreenActivity extends AppCompatActivity /*implements Serializable */{
    //////////////////////////////////////////////Jerome///////////////////////////////////////////
    private static final String TAG = "9527";
    private static final int UNKNOWN_RENDERER = -1;
    private static final int FORWARD_RENDERER = 0;
    private static final int DEFERRED_RENDERER = 1;

    private static final int SET_UNKNOWN = -1;
    private static final int SET_MODEL = 0;
    private static final int SET_SSAO = 1;
    private static final int SET_SSSSS = 2;
    private static final int SET_SSAO_RADIUS = 3;
    private static final int SET_SSAO_BIAS = 4;
    private static final int SET_SSAO_COEFFICIENT = 5;
    private static final int SET_SSAO_KERNEL_SIZE = 6;
    private static final int SET_BACKEND = 7;

    private boolean mBackend = false;
    private GLSurfaceView mGLSurfaceView;
    private VKSurfaceView mVKSurfaceView;
    protected static final float FLIP_DISTANCE = 50;
    GestureDetector mDetector;
    DemoRenderer mRender;
    ///////////////////////////////////////////////////////////////////////////////////////////////
    private void setSSAORadiusSeekBar() {
        SeekBar seekBar = (SeekBar) findViewById(R.id.seekBarRadius);
        // set default value
        seekBar.setProgress(5);
        TextView textView = (TextView) findViewById(R.id.textRadius);
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                textView.setText("Radius:"   Integer.toString(progress));
                mRender.SetInt(SET_SSAO_RADIUS, progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });
    }

    private void setSSAOBiasSeekBar() {
        SeekBar seekBar = (SeekBar) findViewById(R.id.seekBarBias);
        // set default value
        seekBar.setProgress(5);
        TextView textView = (TextView) findViewById(R.id.textBias);
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                textView.setText("Bias:"   Integer.toString(progress));
                mRender.SetInt(SET_SSAO_BIAS, progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });
    }

    private void setSSAOCoefficientSeekBar() {
        SeekBar seekBar = (SeekBar) findViewById(R.id.seekBarCoefficient);
        // set default value
        seekBar.setProgress(150);
        TextView textView = (TextView) findViewById(R.id.textCoefficient);
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                textView.setText("Coefficient:"   Integer.toString(progress));
                mRender.SetInt(SET_SSAO_COEFFICIENT, progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });
    }

    private void setSSAOKernelSizeSeekBar() {
        SeekBar seekBar = (SeekBar) findViewById(R.id.seekBarKernelSize);
        // set default value
        seekBar.setProgress(2);
        TextView textView = (TextView) findViewById(R.id.textKernelSize);
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                textView.setText("Kernel Size:"   Integer.toString(progress * 8));
                mRender.SetInt(SET_SSAO_KERNEL_SIZE, progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });
    }

    private void setSSAOCheckBox() {
        CheckBox ssao = (CheckBox) findViewById(R.id.ssao_check_box);
        ssao.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean checked = ((CheckBox)v).isChecked();
                mRender.SetSSAO(checked);
            }
        });
    }

    private void setSSSSSCheckBox() {
        CheckBox sssss = (CheckBox) findViewById(R.id.sssss_check_box);
        sssss.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean checked = ((CheckBox)v).isChecked();
                mRender.SetSSSSS(checked);
            }
        });
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo_fullscreen);

        //////////////////////////////////////////////Jerome///////////////////////////////////////
        // 设置横屏
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        // 隐藏导航栏
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        // 隐藏应用标题栏
        getSupportActionBar().hide();

        setSSAOCheckBox();
        setSSSSSCheckBox();
        setSSAORadiusSeekBar();
        setSSAOBiasSeekBar();
        setSSAOCoefficientSeekBar();
        setSSAOKernelSizeSeekBar();
        rendererDraw();
        ///////////////////////////////////////////////////////////////////////////////////////////
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
    }

    //////////////////////////////////////////////Jerome///////////////////////////////////////////
    private void rendererDraw() {

        Bundle bundle = getIntent().getExtras();
        if (bundle == null) return;

        if (bundle.containsKey("Backend")) {
            mBackend = bundle.getBoolean("Backend");
        }

        if (mBackend) { // Vulkan
            Log.d("9527", "init VKSurfaceView");
            mVKSurfaceView = (VKSurfaceView)findViewById(R.id.vk_surface_view);
            SurfaceHolder holder = mVKSurfaceView.getHolder();
            mRender = new DemoRenderer(this, holder.getSurface());
            mVKSurfaceView.setRenderer(mRender);
        } else { // GLES
            Log.d("9527", "init GLSurfaceView");
            mGLSurfaceView = (GLSurfaceView)findViewById(R.id.gl_surface_view);
            mGLSurfaceView.setEGLContextClientVersion(2);
            SurfaceHolder holder = mGLSurfaceView.getHolder();
            mRender = new DemoRenderer(this, holder.getSurface());
            mGLSurfaceView.setRenderer(mRender);
            mGLSurfaceView.getAlpha();
        }

        mRender.SetInt(SET_SSAO_RADIUS, 5);
        mRender.SetInt(SET_SSAO_BIAS, 5);
        mRender.SetInt(SET_SSAO_COEFFICIENT, 150);
        mRender.SetInt(SET_SSAO_KERNEL_SIZE, 2);

        int renderer = UNKNOWN_RENDERER;
        if (bundle.containsKey("Renderer")) {
            renderer = bundle.getInt("Renderer");
            mRender.SetRenderer(renderer);
        }

        if (bundle.containsKey("Backend")) {
            mRender.SetInt(SET_BACKEND, mBackend ? 1 : 0);
        }

        if (renderer != DEFERRED_RENDERER) {
            CheckBox ssao = (CheckBox) findViewById(R.id.ssao_check_box);
            ssao.setEnabled(false);
        } else if (bundle.containsKey("SSAO")) {
            boolean isChecked = bundle.getBoolean("SSAO");
            mRender.SetSSAO(isChecked);
            CheckBox ssao = (CheckBox) findViewById(R.id.ssao_check_box);
            ssao.setChecked(isChecked);
        }

        if (renderer != DEFERRED_RENDERER) {
            CheckBox sssss = (CheckBox) findViewById(R.id.sssss_check_box);
            sssss.setEnabled(false);
        } else if (bundle.containsKey("SSSSS")) {
            mRender.SetSSSSS(bundle.getBoolean("SSSSS"));
        }
        if (bundle.containsKey("Model")) {
            mRender.SetModel(bundle.getInt("Model"));
        }

        mDetector = new GestureDetector(this, new GestureDetector.OnGestureListener() {

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                // TODO Auto-generated method stub
                return false;
            }

            @Override
            public void onShowPress(MotionEvent e) {
                // TODO Auto-generated method stub
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                // TODO Auto-generated method stub
                return false;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                // TODO Auto-generated method stub
            }

            /**
             *
             * e1 The first down motion event that started the fling. e2 The
             * move motion event that triggered the current onFling.
             */
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                if (e1.getX() - e2.getX() > FLIP_DISTANCE) {
                    Log.d(TAG, "Slide left...");
                    return true;
                }
                if (e2.getX() - e1.getX() > FLIP_DISTANCE) {
                    Log.d(TAG, "Slide right...");
                    return true;
                }
                if (e1.getY() - e2.getY() > FLIP_DISTANCE) {
                    Log.d(TAG, "Slide up...");
                    return true;
                }
                if (e2.getY() - e1.getY() > FLIP_DISTANCE) {
                    Log.d(TAG, "Slide down...");
                    return true;
                }

                Log.d(TAG, e2.getX()   " "   e2.getY());

                return false;
            }

            @Override
            public boolean onDown(MotionEvent e) {
                // TODO Auto-generated method stub
                return false;
            }
        });
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        //Log.d(TAG, "===> MainActivity call dispatchTouchEvent()");
        //Log.d(TAG, "===> super.dispatchTouchEvent() default return true");
        //Log.d(TAG, "--------------------------------------------------");
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public void onUserInteraction() {
        //Log.d(TAG, "===> MainActivity call onUserInteraction()");
        //Log.d(TAG, "--------------------------------------------------");
        super.onUserInteraction();
    }

    float Finger_0_DownX = 0;
    float Finger_0_DownY = 0;
    float Finger_1_DownX = 0;
    float Finger_1_DownY = 0;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                int mActivePointerId =0;
                int idx = event.findPointerIndex(mActivePointerId);
                if (idx >=0 ) {
                    Finger_0_DownX = event.getX(idx);
                    Finger_0_DownY = event.getY(idx);
                    mRender.setFingerDown(0, Finger_0_DownX, Finger_0_DownY);
                }
                break;
            case MotionEvent.ACTION_UP:
                Finger_0_DownX = 0.0f;
                Finger_0_DownY = 0.0f;
                mRender.setFingerUp(0);
                break;
            default:
                break;
        }

        switch(event.getActionMasked()) {
            case MotionEvent.ACTION_POINTER_DOWN:
                int mActivePointerId = 1;
                int idx = event.findPointerIndex(mActivePointerId);
                if (idx >=0 ) {
                    Finger_1_DownX = event.getX(idx);
                    Finger_1_DownY = event.getY(idx);
                    mRender.setFingerDown(1, Finger_1_DownX, Finger_1_DownY);
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                Finger_1_DownX = 0.0f;
                Finger_1_DownY = 0.0f;
                mRender.setFingerUp(1);
                break;
            default:
                break;
        }

        if (Finger_0_DownX != 0.0f && Finger_0_DownY != 0.0f) {
            int mActivePointerId =0;
            int idx = event.findPointerIndex(mActivePointerId);
            if (idx >=0 ) {
                mRender.setFingerPosition(0, event.getX(idx), event.getY(idx));
            }
        }

        if (Finger_1_DownX != 0.0f && Finger_1_DownY != 0.0f) {
            int mActivePointerId = 1;
            int idx = event.findPointerIndex(mActivePointerId);
            if (idx >=0 ) {
                mRender.setFingerPosition(1, event.getX(idx), event.getY(idx));
            }
        }
        return mDetector.onTouchEvent(event);
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////
}

Here is the activity layout.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@ id/frameLayout3"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?attr/fullscreenBackgroundColor"
    android:theme="@style/ThemeOverlay.GraphicsDebugger.FullscreenContainer"
    tools:context=".DemoFullscreenActivity">

    <android.opengl.GLSurfaceView
        android:id="@ id/gl_surface_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <com.example.graphicsdebugger.VKSurfaceView
        android:id="@ id/vk_surface_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <CheckBox
        android:id="@ id/ssao_check_box"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:text="SSAO"
        app:layout_constraintBottom_toTopOf="@ id/sssss_check_box"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.019"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.728" />

    <CheckBox
        android:id="@ id/sssss_check_box"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="272dp"
        android:text="SSSSS"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.019"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@ id/textRadius"
        android:layout_width="72dp"
        android:layout_height="35dp"
        android:text="Radius:5"
        app:layout_constraintBottom_toBottomOf="@ id/gl_surface_view"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.175"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.101" />

    <TextView
        android:id="@ id/textCoefficient"
        android:layout_width="111dp"
        android:layout_height="35dp"
        android:text="Coefficient:150"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.419"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.101" />

    <TextView
        android:id="@ id/textBias"
        android:layout_width="72dp"
        android:layout_height="35dp"
        android:text="Bias:5"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.68"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.101" />

    <TextView
        android:id="@ id/textKernelSize"
        android:layout_width="111dp"
        android:layout_height="35dp"
        android:text="Kernel Size:16"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.925"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.101" />

    <SeekBar
        android:id="@ id/seekBarKernelSize"
        android:layout_width="146dp"
        android:layout_height="28dp"
        android:max="8"
        android:min="1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.935"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.043" />

    <SeekBar
        android:id="@ id/seekBarCoefficient"
        android:layout_width="146dp"
        android:layout_height="28dp"
        android:max="300"
        android:min="100"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.408"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.041" />

    <SeekBar
        android:id="@ id/seekBarRadius"
        android:layout_width="146dp"
        android:layout_height="28dp"
        android:max="100"
        android:min="0"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@ id/gl_surface_view"
        app:layout_constraintHorizontal_bias="0.141"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.04" />

    <SeekBar
        android:id="@ id/seekBarBias"
        android:layout_width="146dp"
        android:layout_height="28dp"
        android:max="30"
        android:min="0"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@ id/gl_surface_view"
        app:layout_constraintHorizontal_bias="0.675"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.041" />

</androidx.constraintlayout.widget.ConstraintLayout>

Here is the AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.graphicsdebugger">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.GraphicsDebugger">
        <activity android:name=".RendererSettingsActivity"></activity>
        <activity
            android:name=".DemoFullscreenActivity"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:label="@string/title_activity_demo_fullscreen"
            android:theme="@style/Theme.GraphicsDebugger.Fullscreen"
            android:launchMode="singleInstance"/>
        <activity android:name=".RenderingEngineActivity" />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

CodePudding user response:

In the tag of AndroidManifest.xml, add the line android:screenOrientation="portrait"

Thanks

  • Related