如何在Android活动中永久隐藏导航栏?


80

我想在我的活动中永久隐藏导航栏(而不是整个系统ui)。现在我正在使用这段代码

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

它隐藏了该条,但是当用户触摸屏幕时它再次显示。有什么方法可以永久隐藏它,直到活动结束onStop();



在此Google / Android官方链接中,此处列出了许多详细的详细信息:启用全屏模式
克里斯·斯普拉格

当用户根据文档触摸屏幕时,该标志会自动清除。您必须对UI设计进行更改才能始终隐藏导航栏。
user1154390

Answers:


117

片段:

FullScreenFragment.java

HideNavigationBarComponent.java


这是针对Android 4.4+

尝试沉浸式模式https://developer.android.com/training/system-ui/immersive.html

快速摘要(针对Activity类):

private int currentApiVersion;

@Override
@SuppressLint("NewApi")
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    currentApiVersion = android.os.Build.VERSION.SDK_INT;

    final int flags = 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;

    // This work only for android 4.4+
    if(currentApiVersion >= Build.VERSION_CODES.KITKAT)
    {

        getWindow().getDecorView().setSystemUiVisibility(flags);

        // Code below is to handle presses of Volume up or Volume down.
        // Without this, after pressing volume buttons, the navigation bar will
        // show up and won't hide
        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(flags);
                    }
                }
            });
    }

}


@SuppressLint("NewApi")
@Override
public void onWindowFocusChanged(boolean hasFocus)
{
    super.onWindowFocusChanged(hasFocus);
    if(currentApiVersion >= Build.VERSION_CODES.KITKAT && 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);
    }
}

如果在按“提高音量”或“降低音量”时遇到问题,则会显示导航栏。我添加的代码onCreatesetOnSystemUiVisibilityChangeListener

这是另一个相关的问题:

按下音量或最小化还原后,沉浸式导航变得很粘


4
当用户滑动屏幕的顶部/底部时,将显示半透明导航栏暂时出现,然后再次隐藏。也可以隐藏它吗?
Finder 2014年

@KarthickRamu我找到了一种方法,只看一下我的回答即可:)
Muhammed Refaat 2014年

1
@MuhammedRefaat您的提示需要一个植根设备:(
Finder

1
@DawidDrozd谢谢,但是我有一个问题,我的活动根目录布局是RelativeLayout,并且它的子视图已设置为android:layout_alignParentBottom =“ true”,导航栏消失了,但子视图没有移动到底部边缘屏幕上的内容,好像导航栏设置为“不可见”没有消失,您能帮上忙吗?
杰克

1
如果要利用导航栏占用的空间,则必须android:fitsSystemWindows="true"从视图中删除所有出现的情况。生成某些布局时,Android Studio包含此属性。请参阅stackoverflow.com/a/42501330/650894
Joe Lapp

62

做这个。

public void FullScreencall() {
    if(Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
        View v = this.getWindow().getDecorView();
        v.setSystemUiVisibility(View.GONE);
    } else if(Build.VERSION.SDK_INT >= 19) {
        //for new api versions.
        View decorView = getWindow().getDecorView();
        int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
        decorView.setSystemUiVisibility(uiOptions);
    }
}

这可以100%起作用,并且即使API的版本太晚,您也可以对较低的API版本执行相同的操作,我希望它会对其他人有所帮助。

如果您希望这是永久的,只需FullscreenCall()在您的onResume()方法内部调用。


2
我建议您看一下developer.android.com/training/system-ui/immersive.html,它说明您的方法只是隐藏条形,直到发生交互,然后在交互完成后不久再次显示。
被遗弃的购物车

非常感谢-做到了!:D:+1
Christopher Stock

5

对于正在寻找更简单解决方案的人们,我认为您只需在其中包含这一行代码 onStart()

  getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_HIDE_NAVIGATION|
            View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);

这称为沉浸模式。您可以查看官方文档以了解其他可能性。


4

根据Android开发者网站

我认为您不能(据我所知)永久隐藏导航栏。

但是,您可以做一招。这是一个技巧。

只是当navigation bar用户触摸屏幕时出现。立即将其再次隐藏。很有趣。

检查一下

void setNavVisibility(boolean visible) {
int newVis = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        | SYSTEM_UI_FLAG_LAYOUT_STABLE;
if (!visible) {
    newVis |= SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_FULLSCREEN
            | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}

// If we are now visible, schedule a timer for us to go invisible.
if (visible) {
    Handler h = getHandler();
    if (h != null) {
        h.removeCallbacks(mNavHider);
        if (!mMenusOpen && !mPaused) {
            // If the menus are open or play is paused, we will not auto-hide.
            h.postDelayed(mNavHider, 1500);
        }
    }
}

// Set the new desired visibility.
setSystemUiVisibility(newVis);
mTitleView.setVisibility(visible ? VISIBLE : INVISIBLE);
mPlayButton.setVisibility(visible ? VISIBLE : INVISIBLE);
mSeekView.setVisibility(visible ? VISIBLE : INVISIBLE);
}

有关此更多信息,请参见此。

在平板电脑中隐藏系统栏


3

使用:-

view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

在运行Android 4+的平板电脑中,无法隐藏系统/导航栏。

文档

SYSTEM_UI_FLAG_HIDE_NAVIGATION是一个新标志,要求完全隐藏导航栏。请注意,这仅适用于某些手机使用的导航栏(它不会隐藏平板电脑上的系统栏)。


2

这是我的解决方案:

首先,定义布尔值,以指示导航栏是否可见。

boolean navigationBarVisibility = true //because it's visible when activity is created

第二种创建方法隐藏导航栏。

private void setNavigationBarVisibility(boolean visibility){
    if(visibility){
        View decorView = getWindow().getDecorView();
        int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN;
        decorView.setSystemUiVisibility(uiOptions);
        navigationBarVisibility = false;
    }

    else
        navigationBarVisibility = true;
}

默认情况下,如果在隐藏导航栏后单击活动,则导航栏将可见。因此,我们得到了它的状态(如果可见),我们将其隐藏。

现在将OnClickListener设置为您的视图。我使用surfaceview,所以对我来说:

    playerSurface.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            setNavigationBarVisibility(navigationBarVisibility);
        }
    });

另外,启动活动时必须调用此方法。因为我们想在一开始就隐藏它。

        setNavigationBarVisibility(navigationBarVisibility);

2

其安全性问题:https : //stackoverflow.com/a/12605313/1303691

因此,在视图创建开始时,仅通过一次调用就不可能在平板电脑上永久隐藏导航。它会被隐藏,但是在触摸屏幕时会弹出。因此,仅第二次触摸屏幕即可在布局上引起onClickEvent。因此,您需要拦截此呼叫,但是我尚未对其进行管理,当我发现它时,我将更新我的答案。还是您现在已经答案了?


1

我认为打击代码将为您提供帮助,并在setContentView()之前添加这些代码

getWindow().setFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

将这些代码添加到setContentView()getWindow()。getDecorView()。setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE)之后;


1
字段要求API级别21+
zackygaurav '17

1

其他答案大多使用中的setSystemUiVisibility()方法的标志View。但是,从Android 11开始不推荐使用此API。有关更多信息,请参阅我的文章,有关修改系统UI可见性。本文还介绍了如何正确处理切口或如何收听可见性更改。

以下是用于使用新API显示/隐藏系统栏的代码段,以及为了向后兼容而弃用的代码段:

/**
 * Hides the system bars and makes the Activity "fullscreen". If this should be the default
 * state it should be called from [Activity.onWindowFocusChanged] if hasFocus is true.
 * It is also recommended to take care of cutout areas. The default behavior is that the app shows
 * in the cutout area in portrait mode if not in fullscreen mode. This can cause "jumping" if the
 * user swipes a system bar to show it. It is recommended to set [WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER],
 * call [showBelowCutout] from [Activity.onCreate]
 * (see [Android Developers article about cutouts](https://developer.android.com/guide/topics/display-cutout#never_render_content_in_the_display_cutout_area)).
 * @see showSystemUI
 * @see addSystemUIVisibilityListener
 */
fun Activity.hideSystemUI() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        window.insetsController?.let {
            // Default behavior is that if navigation bar is hidden, the system will "steal" touches
            // and show it again upon user's touch. We just want the user to be able to show the
            // navigation bar by swipe, touches are handled by custom code -> change system bar behavior.
            // Alternative to deprecated SYSTEM_UI_FLAG_IMMERSIVE.
            it.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
            // make navigation bar translucent (alternative to deprecated
            // WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
            // - do this already in hideSystemUI() so that the bar
            // is translucent if user swipes it up
            window.navigationBarColor = getColor(R.color.internal_black_semitransparent_light)
            // Finally, hide the system bars, alternative to View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            // and SYSTEM_UI_FLAG_FULLSCREEN.
            it.hide(WindowInsets.Type.systemBars())
        }
    } else {
        // Enables regular immersive mode.
        // For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE.
        // Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY
        @Suppress("DEPRECATION")
        window.decorView.systemUiVisibility = (
                // Do not let system steal touches for showing the navigation bar
                View.SYSTEM_UI_FLAG_IMMERSIVE
                        // Hide the nav bar and status bar
                        or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        or View.SYSTEM_UI_FLAG_FULLSCREEN
                        // Keep the app content behind the bars even if user swipes them up
                        or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
        // make navbar translucent - do this already in hideSystemUI() so that the bar
        // is translucent if user swipes it up
        @Suppress("DEPRECATION")
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
    }
}

/**
 * Shows the system bars and returns back from fullscreen.
 * @see hideSystemUI
 * @see addSystemUIVisibilityListener
 */
fun Activity.showSystemUI() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        // show app content in fullscreen, i. e. behind the bars when they are shown (alternative to
        // deprecated View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION and View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
        window.setDecorFitsSystemWindows(false)
        // finally, show the system bars
        window.insetsController?.show(WindowInsets.Type.systemBars())
    } else {
        // Shows the system bars by removing all the flags
        // except for the ones that make the content appear under the system bars.
        @Suppress("DEPRECATION")
        window.decorView.systemUiVisibility = (
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
    }
}

我在模拟器上使用BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE标志尝试了您的代码,但是当我触摸屏幕时,导航栏将弹出并保持显示状态。知道我还应该设置什么才能在Android 11上获得STICKY功能吗?
天使哥

@AngelKoh如果要隐藏它,必须手动调用hideSystemUI()。检查我的答案中提到的文章,其中包含所有这些详细信息。粘滞模式意味着如果用户向上滑动这些条,这些条将是透明的,并且该应用也将接收触摸事件(请参阅developer.android.com/training/system-ui/…)。
米洛什Černilovský

是的,将调用hideSystemUI(),并且第一次将Ui隐藏。但是,当我随后触摸屏幕时,导航栏会弹出并保持显示状态。
Koh

BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE的目的是防止系统窃取触摸并显示横条。因此,我不确定在不查看/调试实际应用程序的情况下可能导致此问题的原因。
–MilošČernilovský

0

试试这个:

View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
          | View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);

不,它给我同样的结果
Sujith Manjavana 2014年

0

我认为这段代码可以解决您的问题。将此代码复制并粘贴到MainActivity.java中

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

    View decorView = getWindow().getDecorView();
    decorView.setOnSystemUiVisibilityChangeListener
    (new View.OnSystemUiVisibilityChangeListener() {
        @Override
        public void onSystemUiVisibilityChange(int visibility) {

            if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                hideNavigationBar();
            } 
        }
    });
}



private void hideNavigationBar() {
   getWindow().getDecorView().setSystemUiVisibility(
        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION|
        View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}

它将在Android-10上运行。我希望这会有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.