Immersive mode navigation becomes sticky after volume press or minimise-restore

匿名 (未验证) 提交于 2019-12-03 02:45:02

问题:

public class MainActivity extends Activity {      @Override     protected void onCreate(Bundle savedInstanceState) {         this.getWindow().getDecorView().setSystemUiVisibility(getSystemUiFlags());         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);     }      private static int getSystemUiFlags() {             return View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION                     | View.SYSTEM_UI_FLAG_LAYOUT_STABLE                     | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN                     | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;     }  } 

After first start

After volume buttons pressed or after recent apps pressed twice

I saw QuickPic app doesn't have this bug. I wonder how they omitted it.

回答1:

The following code works for me:

public void updateUI() {     final View decorView = getWindow().getDecorView();     decorView.setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() {         @Override         public void onSystemUiVisibilityChange(int visibility) {             if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {                 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                             | View.SYSTEM_UI_FLAG_FULLSCREEN                             | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);                 }             }         }); } 

And called the listener on onCreate and onResume methods:

@Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     updateUI(); }  @Override public void onResume() {     super.onResume();     updateUI(); } 


回答2:

I had the same problem, and I solved it with a simple workaround. Even though I couldn't find the theoretical reason of this workaround, but it worked for me anyway.

It seems like when a volume button is pressed, the 'flags' related to the 'immersive mode' are cleared. And I think that's why the immersive mode is disabled and the immersive mode is not restored automatically.

Therefore, I tried to set the 'flags' after pressing the volume button with 'runnable' object.

So, it works like this:

immersive mode -> volume button pressed(flags cleared) -> 500ms later, the runnable object sets the flags again -> immersive mode restored

1. First, define the runnable object to set the flags

private Runnable decor_view_settings = new Runnable() {     public void run()      {         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);     } }; 

2. Post the runnable object with some delay to a handler when a volume button is pressed

private Handler mHandler = new Handler(); 

...

@Override  public boolean onKeyDown(int keyCode, KeyEvent event)  {     if(keyCode == KeyEvent.KEYCODE_BACK)     {         finish();     }     else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP)     {         mHandler.postDelayed(decor_view_settings, 500);     }      return super.onKeyDown(keyCode, event); } 

I just delayed it for 500ms with no reason, it's not important.

3. The basic code for immersive mode with runnable object

@Override public void onWindowFocusChanged(boolean hasFocus)  {     super.onWindowFocusChanged(hasFocus);      if(hasFocus)      {         mHandler.post(decor_view_settings);     } } 

It worked perfectly on my app.

So, when I press a volume button, the immersive mode is disabled and the volume rocker pops up.

after a few seconds, the volume rocker disappears and so does the status bar and the navigation bar.

Hope this work for you.



回答3:

My solution is to set the UI-Visibility flags in three places:

  1. When getting the focus
  2. In onResume
  3. In the OnSystemUiVisibilityChangeListener listener

The third solved my problem. The others might not be needed, but I left them. This is what is looks like:

  private void setupMainWindowDisplayMode() {     View decorView = setSystemUiVisilityMode();     decorView.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {       @Override       public void onSystemUiVisibilityChange(int visibility) {         setSystemUiVisilityMode(); // Needed to avoid exiting immersive_sticky when keyboard is displayed       }     });   }    private View setSystemUiVisilityMode() {     View decorView = getWindow().getDecorView();     int options;     options =         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;      decorView.setSystemUiVisibility(options);     return decorView;   } 

setupMainWindowDisplayMode() gets called in onCreate().



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!