Android 按下音量或最小化恢复后,沉浸式模式导航变得粘滞

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21164836/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:04:24  来源:igfitidea点击:

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

androidandroid-fullscreen

提问by Yaroslav Mytkalyk

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 first start

第一次启动后

After volume buttons pressed or after recent apps pressed twice

按下音量按钮后或按下最近的应用程序两次后

enter image description here

在此处输入图片说明

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

我看到 QuickPic 应用程序没有这个错误。我想知道他们是如何省略它的。

回答by emjee

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 onCreateand onResumemethods:

并调用侦听器onCreateonResume方法:

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

@Override
public void onResume() {
    super.onResume();
    updateUI();
}

回答by Chris

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

我的解决方案是在三个地方设置 UI-Visibility 标志:

  1. When getting the focus
  2. In onResume
  3. In the OnSystemUiVisibilityChangeListener listener
  1. 获得焦点时
  2. 在简历中
  3. 在 OnSystemUiVisibilityChangeListener 监听器中

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().

setupMainWindowDisplayMode() 在 onCreate() 中被调用。

回答by Sangseok

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

沉浸式模式 -> 按下音量按钮(清除标志)-> 500 毫秒后,可运行对象再次设置标志 -> 沉浸式模式恢复

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

1.首先定义runnable对象来设置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

2.当按下音量按钮时,将可运行对象延迟一段时间发布到处理程序

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.

我只是无缘无故地延迟了 500 毫秒,这并不重要。

3. The basic code for immersive mode with runnable object

3.具有可运行对象的沉浸模式的基本代码

@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.

希望这对你有用。