Thursday, June 5, 2014

Android Immersive Mode for Dialog

This post is going to be discussed about the problem of Immersive Mode for Dialog.

Before going to the details we need to know about Immersive Mode and the usage?

Everyone knows andorid came up with KitKat 4.4 version and it bought new features and improvements.

Such in case, Immersive mode is one among them, which allows developers to take advantage of full screen from edge to edge on phones and tablets, hiding all system UI such as the status bar and navigation bar.

To make sure that users always have easy, consistent access to system UI from full-screen immersive mode, Android 4.4 supports a new gesture — in immersive mode, an edge swipe from the top or bottom of the screen now reveals the system UI.

To return to immersive mode, users can touch the screen outside of the bar bounds or wait for a short period for the bars to auto-hide. For a consistent user experience, the new gesture also works with previous methods of hiding the status bar.

How to Use the Immersive Mode?

// This snippet hides the system bars.
private void hideSystemUI() {
    // Set the IMMERSIVE flag.
    // Set the content to appear under the system bars so that the content
    // doesn't resize when the system bars hide and show.
    mDecorView.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);
}
Origin Code Snippet: Immersive Training Material

Before setting the View Flags, know about them.

Flag
Impact
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
Action bar is hidden
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
Hides Navigation Bar
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN   
Hides Status Bar


Coming to the Problem:

When we use Spinner, Alert Dialog, and Dialog and … Immersive mode is not working.
For more Information visit the link Android Issue regrading Immersive Mode

Why this Problem is Occurring for Dialog and so on...?

Each Dialog, Alert Dialog, Spinners are having their own window and it is not accessing application window.

So the flags which we are used for application window is not impacting the Dialog, Alert Dialog window.

How to Solve this Issue for Dialog Box?

Here we should know about the FLAG_NOT_FOCUSABLE flag, which helps us in solving the issue and then just add the same Immersive Flags to the Dialog, it works as we expect.

Setting this flag implies that the window will not need to interact with a soft input methodSo, Once the dialog is created and shown then clear the flag, otherwise we can’t get access to the Navigation Bar UI keys like back, home and etc..

Look at the snippet:

final Dialog dialog = new Dialog(v.getContext());
dialog.setCanceledOnTouchOutside(false);

dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);

dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

dialog.getWindow().getDecorView().setSystemUiVisibility(
          View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
          | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
      | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
      | View.SYSTEM_UI_FLAG_FULLSCREEN
      | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
      | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);

dialog.setContentView(R.layout.dialog_custom);
dialog.setTitle("Immersive Mode Dialog");

dialog.findViewById(R.id.dialogBtnYes).setOnClickListener(new OnClickListener() {
          @Override
      public void onClick(View v) {
          dialog.dismiss();
           }
          });

dialog.findViewById(R.id.dialogBtnNo).setOnClickListener(new OnClickListener() {
          @Override
      public void onClick(View v) {
          dialog.dismiss();
            }
          });

dialog.show();

dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);


Now check the dialog box, how it appears...


Happy Coding.. :) 

Screen shot:





Source Code
You can download the source code by clicking here: Source.  This project is built using eclipse IDE. Unzip and import the project into Eclipse, it’s a good idea to use the Project by clean and rebuild from the project menu. It works from API level 19.

Thanks for reading :) 
Whether this post is helpful?

Have something to add to this post? If you have any other quick thoughts/hints that you think people will find useful? feedback's are welcome...

5 comments :

  1. For info, I managed to get this working using DialogFragment. See my post here : http://stackoverflow.com/a/24549869/1532108

    ReplyDelete
  2. Your smart solution indeed works for custom dialogs.
    But what about spinners such as menus for which the problem also occurs?

    ReplyDelete
    Replies
    1. Its bug and posted in https://code.google.com/p/android/issues/detail?id=68031 issues.
      There is no direct solution to solve this issue and one of the workaround for the dialog box shown in the post.
      If you want to achieve for everything then there is solution to do and one of the developer made an app and published in google play https://play.google.com/store/apps/details?id=be.ppareit.immersivemode&hl=en.

      If i want to implement like the app of immersive mode then we need to override the hardware controls like back press, home and etc...

      Delete
  3. It's interesting that many of the bloggers your tips helped to clarify a few things for me as well as giving... very specific nice content.Best Android Training in Velachery | android development course fees in chennai

    ReplyDelete
  4. This information is impressive; I am inspired with your post writing style & how continuously you describe this topic. After reading your post, thanks for taking the time to discuss this, I feel happy about it and I love learning more about this topic.Android Training in chennai | Android Training

    ReplyDelete