onSystemUiVisibilityChange not called after screen rotation - android

I'm trying to have a fullscreen app, with the navigation bar disapearing after few seconds and reappearing on user interaction (like the Android 3d gallery video player behaviour) for Android 4.2.2 (API 17)
To achieve this, i'm using this code :
public class MainActivity extends Activity {
private View mRootView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// OnCreate code ...
mRootView = getWindow().getDecorView();
setOnSystemUiVisibilityChangeListener();
showSystemUi(false);
}
private void showSystemUi(boolean visible) {
int flag = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
if (!visible) {
// We used the deprecated "STATUS_BAR_HIDDEN" for unbundling
flag |= View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
mRootView.setSystemUiVisibility(flag);
}
private void setOnSystemUiVisibilityChangeListener() {
mRootView.setOnSystemUiVisibilityChangeListener(
new View.OnSystemUiVisibilityChangeListener() {
#Override
public void onSystemUiVisibilityChange(int visibility) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
showSystemUi(false);
}
}, 2000);
}
});
}
As you can see, i've been inspired by the Android API and the android 3d gallery code : http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/4.2.2_r1/com/android/gallery3d/app/MoviePlayer.java#MoviePlayer.setOnSystemUiVisibilityChangeListener%28%29
So, here is my problem :
This code works greatly if i don't move the device.
But if i made a screen rotation, the navigation bar will not be displayed, clicking on screen will display it, but the callback onSystemUiVisibilityChange seems to be never called (checked with debugger), so the navigation bar will never disappear. And if i rotate the screen again, it will works again. (In fact, it seems like it only works if i rotate the screen while the navigation bar is displayed)
Does anyone has an idea of where this problem comes from ?
Thx.

Related

How to remove the black bar appearing at the bottom?

I am new to Android Development. I want my app to support the screen size of my device i.e. 1080 x 2160 pixels. Currently there is a black bottom bar that is displayed in place of where the navigation buttons would have been.
Please note that I do not want Full Screen Mode. I have disabled the button navigation on my device. It is only for this app that that the bottom black rectangle is showing.
I just want my app to support the gesture navigation system of my device instead of buttons.How do I make the bottom bar go away using Java (Android Studio) so that my app utilizes that space?
question is old but I faced the same issue and didnot find the solution on SO.
this problem occurs for long screens
We recommend that you design your app to support aspect ratios of 2.1 or higher. For this, you would add the following to the "application" element in your Manifest file:
<meta-data android:name="android.max_aspect" android:value="2.1" />
from here
I had the same issue, updated manifest file with this or remove if you have one.
before
<meta-data
android:name="android.max_aspect"
android:value="2.1" />
after
<meta-data
android:name="android.max_aspect"
android:value="2.4" />
working for me now.
Hi please Try below code
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
You can try this
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
getWindow().getDecorView().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
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
Try to add this code
#Override
protected void onCreate(Bundle savedInstanceState) {
...
hideSystemUI(this, 1000);
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
// Hide bar after 1 second
hideSystemUI(this, 1000);
}
}
public static void hideSystemUI(#NonNull final Activity activity, final int delayMs) {
View decorView = activity.getWindow().getDecorView();
int uiState = View.SYSTEM_UI_FLAG_IMMERSIVE
| 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
| View.SYSTEM_UI_FLAG_FULLSCREEN;
final Handler handler = new Handler();
decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
#Override
public void onSystemUiVisibilityChange(int visibility) {
if (visibility == View.VISIBLE) {
Runnable runnable = new Runnable() {
#Override
public void run() {
hideSystemUI(activity, 1000);
}
};
handler.postDelayed(runnable, delayMs);
}
}
});
decorView.setSystemUiVisibility(uiState);
}
WARNING
If you have two activities, add this before changing
View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(null);

Does SimpleExoPlayerView have controller visibility changed events?

I'm trying to implement a full screen mode with SimpleExoPlayerView. I've got this mostly working using setSystemUiVisibility.
During onCreate i add a OnSystemUiVisibilityChange listener to sync hiding the player controls with the actionbar.
#Override
public void onCreate(Bundle savedInstanceState) {
View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener
(onSystemUiChange());
hideSystemUI();
}
In the OnSystemUiVisibilityChangeListener i'm also setting a timeout that matches the simpleExoplayerViews timeout so the controls and action bar are hidden at the same time.
#NonNull
private View.OnSystemUiVisibilityChangeListener onSystemUiChange() {
return new View.OnSystemUiVisibilityChangeListener() {
#Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
mSimpleExoPlayerView.showController();
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//sync the hide system ui with
//simpleExoPlayerView's auto hide timeout
hideSystemUI();
}
}, mSimpleExoPlayerView.getControllerShowTimeoutMs());
} else {
mSimpleExoPlayerView.hideController();
}
}
};
}
private void hideSystemUI() {
View rootView = findViewById(R.id.root);
rootView.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
);
}
This works pretty well except in one case. If you tap the screen and then tap it again before the SimpleExoPlayerView controls timeout the SimpleExoPlayerView are hidden but the system ui do not get set until the timeout. Is there any events i can hook into instead?
I've tried setting a onClick and onTouch listener for my root layout but these events are not fired, i suspect SimpleExoPlayerView might be swallowing them?
ExoPlayer 2.10.4 has it.
exoplayer PlayerView has a method called
public void setControllerVisibilityListener(PlayerControlView.VisibilityListener listener) {
}
As of 2.6.1, SimpleExoPlayerView doesn't seem to have any visibility change listeners for the controls, but PlaybackControlView has. However, it's stored in a private field in SimpleExoPlayerView and there's no builtin way to a access it. To set your own listener, you'll either have to:
copy SimpleExoPlayerView.java to your project and make the required changes,
use reflection (don't forget to add proguard rules, if needed),
override exo_simple_player_view.xml and make sure it contains a PlaybackControlView, then find it using findViewById,
find it manually by traversing the view hierarchy.
In my opinion, the first and third options are the nicest, but the last one requires the least amount of changes, and it also works very well. Here is an example:
import com.google.android.exoplayer2.ui.PlaybackControlView;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
public SomeActivity extends Activity implements PlaybackControlView.VisibilityListener {
private initExoPlayer() {
// ...
addPlaybackControlVisibilityListener(mSimpleExoPlayerView, this);
}
#Override
public void onVisibilityChange(int visibility) {
// show/hide system ui here
}
private static void addPlaybackControlVisibilityListener(SimpleExoPlayerView playerView, PlaybackControlView.VisibilityListener listener) {
PlaybackControlView playbackControlView = findPlaybackControlView(playerView);
if (playbackControlView != null)
playbackControlView.setVisibilityListener(listener);
}
private static PlaybackControlView findPlaybackControlView(ViewGroup viewGroup) {
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
if (child instanceof PlaybackControlView)
return (PlaybackControlView) child;
if (child instanceof ViewGroup) {
PlaybackControlView result = findPlaybackControlView((ViewGroup) child);
if (result != null)
return result;
}
}
return null;
}
}
With Exoplayer 2.16.1 you can use setControllerVisibilityListener like this:
viewBinding.playerView.setControllerVisibilityListener { visibility ->
if (visibility == View.VISIBLE) {
// controller is visible
} else {
// controller is not visible
}
}
There are two classes we have 1. PlayerView 2. StyledPlayerView.
I am answering here for StyledPlayerView since PlayerView is deprecated now.
First create a class which extends StyledPlayerView and also your Class do implement this interface class CustomPlayerView extends StyledPlayerView implements StyledPlayerView.ControllerVisibilityListener So you need to override onVisibilityChanged Method:
#Override
public void onVisibilityChanged(int visibility) {
isControllerVisible = visibility == View.VISIBLE;
}
Now you can call this method on some other class where all your playerView methods present
binding.playerView.setControllerVisibilityListener(customPlayerView)
So on Visibility change of your controls you will get callbacks.

Status bar background stays on screen when entering immersive mode?

I've been searching everywhere but I'm at a loss about that : trying to activate immersive mode on a project;
Nearly everything works fine, except the background of my status bar always stays there, spoiling the immersion...
I have included a screenshot of the screen before and after activating the immersive mode, and set the "colorPrimaryDark" to full green for max contrast :
screenshots showing the background of the status bar when nothing should be there
The code I used and reinserted in a blank project to isolate this problem comes straight from the google dev examples, in my MainActivity, I have :
private final String TAG = "DEBUG::" + this.getClass().getSimpleName();
private final int INITIAL_HIDE_DELAY = 1500;
private View decorView;
private Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//setting needed decorView for fullscreen behavior
decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(onSystemUiVisibilityChangeListener);
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Log.i(TAG, "onWindowFocusChanged::hasFocus = " + hasFocus);
if (hasFocus) {// When the window gains focus, hide the system UI.
delayedHide(INITIAL_HIDE_DELAY);
} else {// When the window loses focus, cancel any pending hide action.
mHideHandler.removeMessages(0);
}
}
private void hideSystemUI() {
Log.i(TAG, "hideSystemUI");
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
uiOptions |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
uiOptions |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
uiOptions |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
uiOptions |= View.SYSTEM_UI_FLAG_FULLSCREEN;
uiOptions |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
uiOptions |= View.SYSTEM_UI_FLAG_IMMERSIVE;
decorView.setSystemUiVisibility(uiOptions);
}
private final Handler mHideHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
hideSystemUI();
}
};
private void delayedHide(int delayMillis) {
Log.i(TAG, "delayedHide");
mHideHandler.removeMessages(0);
mHideHandler.sendEmptyMessageDelayed(0, delayMillis);
}
private View.OnSystemUiVisibilityChangeListener onSystemUiVisibilityChangeListener =
new View.OnSystemUiVisibilityChangeListener() {
#Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
// The system bars are visible
getSupportActionBar().show();
delayedHide(INITIAL_HIDE_DELAY);
} else {
// The system bars are NOT visible
getSupportActionBar().hide();
}
}
};
I wonder if my problem might come from layout or style files, but those are raw from project generation...
I hope someone out there can point me to where I failed!
Thanks in advance!
EDIT : I found that removing : android:fitsSystemWindows="true" from my activity's layout file allows a real fullscreen mode, but then, my ActionBar is partly hidden behind the StatusBar -when showing. Could it be that when I set my getSupportActionBar().show(); in onSystemUiVisibilityChangeListener, it gets drawn too soon?
EDIT 2 : How I understand this so far is that I only have 2 choices regarding the position/size of my content (action bar included) :
top of the screen, which will show the actionBar partially hidden by the statusbar,
or below the statusBar's bottom, which will leave me with a "hole" when the statusBar is hidden -_-
I am now looking for a solution to animate the ActionBar off-screen/on-screen by myself inside my onSystemUiVisibilityChangeListener method, but can't find a way to grab its View to do so, solutions posted there https://stackoverflow.com/a/21125631/6463888 seem out of date...
I met the same problem today. But I didn't solve this issue by setSystemUiVisibility. I solve it using following method:
hide:enter full screen
mActivity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
show:normal display
mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
So,
the way I solved this may seem a bit stretched, but I'm only a beginner, so feel free to comment!
I don't use getSupportActionBar().show(); or getSupportActionBar().hide(); anymore, but I managed to grab the View that contains the ActionBar which is an AppBarLayout, and I animated this View instead. So I call a small function animateActionBarInOrOut to animate it on or off screen inside onSystemUiVisibilityChange :
private void animateActionBarInOrOut(boolean appears){
Log.i(TAG, "animateActionBarInOrOut::actual position = " + toolbar.getY());
if(appears){
toolbar.animate().translationY(48).alpha(1); // move it out of the screen
}else{
toolbar.animate().translationY(-48).alpha(0); // move it out of the screen
}
}
Although this is not exactly an answer to the initial question, it works as a solution to the problem, one just has to move the content accordingly...
Hi your problem is caused by StatusBar nature, it has a separate layout from your main content and you need to set his color manually. For example when you call onSystemUiVisibilityChange() you can take the color of your background and, after set the color of StatusBar with that color. This is a workaround to avoid 2 different background colors.

Immersive Mode on WebView Application - Text input is covered

I've written a basic application to test the way Immersive Mode or FullScreen mode(only hide status bar) works on a Webview app.
Here's my main_activity. Note this is just a test app that follows the api guidelines as far as I can tell.
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView mWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
// Force links and redirects to open in the WebView instead of in a browser
mWebView.setWebViewClient(new WebViewClient());
mWebView.loadUrl("http://baidu.com"); //just a test website, doesn't matter really. Just need a text box low enough on screen.
setupFullscreenMode();
}
private void setupFullscreenMode() {
View decorView = setFullscreen();
decorView
.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
#Override
public void onSystemUiVisibilityChange(int visibility) {
setFullscreen();
}
});
}
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
setFullscreen();
}
}
private View setFullscreen() {
View decorView = getWindow().getDecorView();
//FLAG ORDERING MAKES A DIFFRENCE
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE // without the other layout flags, this results in glitched out status and navagation spaces
//unsurprisingly everything (pre-selected scenario etc) works fine with this flag, but it's not true fullscreen
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION // This also breaks the pre-seclected scenario
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // This breaks the pre-selected scenario
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION //2
| View.SYSTEM_UI_FLAG_FULLSCREEN //1
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);//3 with 1,2,3 there's some glitching still going on(ghost statusbar)
return decorView;
}
In short this is my bug -
Be in immersive mode and go to a website (baidu in this case) and search for anything..
Scroll down to the text input box and click it. The application should have resized with the input box right above the top of the keyboard.
Hit the little "downward" triangle to dismiss the keyboard. Notice how the input field is left selected still.
(ISSUE) Scroll up enough to lower the input box on screen. Now try tapping on the input box again. The app doesn't resize to accommodate the keyboard.
Expected Behaviour would be to resize the app because that's what happens when I try doing this without fullscreen or immersive mode.
What is going on here that results in a failure ?
In my actual app this is very frustratingly flaky. It may or may not resize the app whether or not the text box is pre-selected.
For now, I'm only interested in understanding this test app's behavior.

Sticky immersive mode disabled after soft keyboard shown

I have an app that needs to be full screen most of the time. I know that if an alert is shown or other window is displayed, over the top of the activity window, full screen is temporarily removed. Unfortunately, when a soft keyboard is shown for an EditText or something, when the user has finished with the keyboard, full screen immersive mode is not restored.
Any idea how this can be achieved?
Taken from this sample app by Google, you need to append this to the end of your activity, before the last end bracket:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
// When the window loses focus (e.g. the action overflow is shown),
// cancel any pending hide action. When the window gains focus,
// hide the system UI.
if (hasFocus) {
delayedHide(300);
} else {
mHideHandler.removeMessages(0);
}
}
private void hideSystemUI() {
getWindow().getDecorView().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 |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_LOW_PROFILE |
View.SYSTEM_UI_FLAG_IMMERSIVE
);
}
private void showSystemUI() {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
}
private final Handler mHideHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
hideSystemUI();
}
};
private void delayedHide(int delayMillis) {
mHideHandler.removeMessages(0);
mHideHandler.sendEmptyMessageDelayed(0, delayMillis);
}
And you should be good. :)
I put this code at onCreate() observer the layout changes
getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int screenHeight = getWindow().getDecorView().getRootView().getHeight();
int keyboardHeight = screenHeight - rect.bottom;
if (keyboardHeight > screenHeight * 0.15) {
setToImmersiveMode();
}
}
});
private void setToImmersiveMode() {
// set to immersive
getWindow().getDecorView().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
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
I suggest extending AppCompatActivity into a new class (ImmersiveAppCompatActivity). By doing this, any activity that you create using this class will have built in handling of immersive mode.
If you try and set immersive mode too quickly after the soft keyboard has appeared, it will not hide.
Also note that the handler has been improved by switching to a static handler - this will prevent leaks if the user leaves the activity before the GUI is hidden.
public abstract class ImmersiveAppCompatActivity extends AppCompatActivity {
private HideHandler mHideHandler;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create a handler to set immersive mode on a delay
mHideHandler = new HideHandler(this);
}
#Override
protected void onResume() {
super.onResume();
setToImmersiveMode();
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus) {
mHideHandler.removeMessages(0);
mHideHandler.sendEmptyMessageDelayed(0, 300);
}
else mHideHandler.removeMessages(0);
}
private void setToImmersiveMode() {
// set to immersive
getWindow().getDecorView().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
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
private static class HideHandler extends Handler {
private final WeakReference<ImmersiveAppCompatActivity> mActivity;
HideHandler(ImmersiveAppCompatActivity activity) {
mActivity = new WeakReference<>(activity);
}
#Override
public void handleMessage(Message msg) {
ImmersiveAppCompatActivity activity = mActivity.get();
if(activity != null) activity.setToImmersiveMode();
}
}
}
Here's the Kotlin version:
abstract class ImmersiveAppCompatActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
setToImmersiveMode()
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
val runnable = Runnable { setToImmersiveMode() }
val handler = Handler(Looper.getMainLooper())
handler.postDelayed(runnable, 300)
}
private fun setToImmersiveMode() {
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
}
Now, create your activity using this class:
public class SettingsActivity extends ImmersiveAppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
}
}
I've tested this in Android 5.1 and 7.0 to work in a full screen app that has no action bar.
Additionally, if you using the keyboard in an EditText be aware of the imeOptions. In landscape mode you can get strange full screen editing behavior. This can be disabled by setting imeOptions flags which are contained in the class EditorInfo:
<EditText
android:layout_width="#dimen/pin_width"
android:layout_height="wrap_content"
android:inputType="numberPassword"
android:imeOptions="flagNoExtractUi"
android:ems="10"
android:id="#+id/editTextPIN"
android:textSize="#dimen/pin_large_text_size"/>
https://developer.android.com/reference/android/view/inputmethod/EditorInfo.html
This is the normal behaviour. But you can fix it in two steps :
1. Find out when the keyboard is hidden
2. Set the immersive fullscreen mode (again)
Step 1 is a little bit tricky. You can check out my answer here:
https://stackoverflow.com/a/27567074/2525452
Step 2 is simple:
public static void setImmersiveMode( Activity activity )
{
// Get the Activity's content View
ViewGroup content = (ViewGroup) activity.findViewById( android.R.id.content );
//
// Set the immersive mode flags at the content View
content.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
);
}
To keep immersive mode as it is while soft input enabled and typing. You need to set flags to your activity window. Not to Decor view.
YourActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
To remove it do just,
YourActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
Also keep your system UI visibility settings as you want on decor view.

Categories

Resources