Search code examples
androidandroid-layoutscreen-rotationandroid-immersive

Using immersive mode only on landscape mode


I try make app that will go to immersive mode on landscape (without status bar and navigation bar) and disable immersive mode on portrate (with return status bar and navigation bar). Without restart activity (onCreate called only one time). I wrote small example app to show my problem.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="test.com.immersivetest">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:padding="0dp"
    tools:context="test.com.immersivetest.MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffff0000"
         />
</RelativeLayout>

MainActivity.java

package test.com.immersivetest;

import android.content.res.Configuration;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    private View activity;
    private View decorView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        activity = findViewById(R.id.activity_main);
        decorView = this.getWindow().getDecorView();
        System.out.println("On Crate");
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        updateForOrientation(newConfig.orientation);
    }

    public void updateForOrientation(int orientation) {
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            hideSystemUI();
        } else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            showSystemUI();
        }
    }



    private void hideSystemUI() {
        System.out.println("Hide UI");
        activity.setFitsSystemWindows(false);
        decorView.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                        | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);

    }

    private void showSystemUI() {
        activity.setFitsSystemWindows(true);
        decorView.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    }


}

Steps to see my problem:

1) Start app (in portrait mode) and in result i see child RelativeLayout with red background on fullscreen with titlebar, statusbar, navigationbar. It's correct. Screenshot

2) Rotate to landscape. And again i see correct result: Child RelativeLayout with red background on immersive mode without titlebar, statusbar, navigationbar.

3) Rotate to portrait. And see correct results: like on screenshot for the first step.

4) Rotate to landscape again. And i see not correct result. Child RelativeLayout not stretched to parent size. We see empty fields on top and bottom of screen. Screenshot with problem

How to fix it? Why all rotations to landscape intead of the first not correct resize child RelativeLayout ?

P.s. Min sdk version 19.


Solution

  • I found solution myself ;) i've got snippets from https://developer.android.com/training/system-ui/immersive.html#nonsticky . And it works not correctly. I changed flags in showSystemUI() and all works perfectly!

    private void showSystemUI() {
        activity.setFitsSystemWindows(true);
        decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
    }
    

    But it work in my main app because i don't use action bar. If action bar enabled then action bar shown not correct. I don't know why. Any way i checked flags on start app and it has only SYSTEM_UI_FLAG_VISIBLE.

    If anyone have solution for app with action bar i will be happy to know solution.