在一个活动中永久隐藏导航栏

44

有没有可能永久删除一个活动上的导航栏?我想要删除平板电脑屏幕下方显示的带有按钮的栏,而不是操作栏。 这里.

我知道这并不被建议,但我不是决定者,我需要这么做。在我的布局中,还有另一个按钮可以离开该活动。我的应用程序的其余部分可以有并且确实有导航栏。

我找到了这段代码并稍微修改了一下。问题是,即使隐藏导航栏,也会留下黑色的空间。我猜系统计算屏幕大小时考虑了导航栏?

public static class Content extends ImageView implements View.OnSystemUiVisibilityChangeListener, View.OnClickListener, ActionBar.OnMenuVisibilityListener {
    Activity mActivity;
    TextView mTitleView;
    Button mPlayButton;
    SeekBar mSeekView;
    boolean mAddedMenuListener;
    boolean mMenusOpen;
    boolean mPaused;
    boolean mNavVisible;
    int mLastSystemUiVis;

    Runnable mNavHider = new Runnable() {
        @Override public void run() {
            setNavVisibility(false);
        }
    };

    public Content(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOnSystemUiVisibilityChangeListener(this);
        setOnClickListener(this);
    }

    public void init(Activity activity, TextView title, Button playButton,
            SeekBar seek) {
        // This called by the containing activity to supply the surrounding
        // state of the video player that it will interact with.
        mActivity = activity;
        mTitleView = title;
        mPlayButton = playButton;
        mSeekView = seek;
        mPlayButton.setOnClickListener(this);
        setPlayPaused(true);
    }

    @Override protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (mActivity != null) {
            mAddedMenuListener = true;
            mActivity.getActionBar().addOnMenuVisibilityListener(this);
        }
    }

    @Override protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mAddedMenuListener) {
            mActivity.getActionBar().removeOnMenuVisibilityListener(this);
        }
    }

    @Override public void onSystemUiVisibilityChange(int visibility) {
        // Detect when we go out of nav-hidden mode, to clear our state
        // back to having the full UI chrome up.  Only do this when
        // the state is changing and nav is no longer hidden.
        int diff = mLastSystemUiVis ^ visibility;
        mLastSystemUiVis = visibility;
        if ((diff&SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
                && (visibility&SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
            setNavVisibility(true);
        }
    }

    @Override protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);

        // When we become visible or invisible, play is paused.
        setPlayPaused(true);
    }

    @Override public void onClick(View v) {
        if (v == mPlayButton) {
            // Clicking on the play/pause button toggles its state.
            setPlayPaused(!mPaused);
        } else {
            // Clicking elsewhere makes the navigation visible.
            setNavVisibility(true);
        }
    }

    @Override public void onMenuVisibilityChanged(boolean isVisible) {
        mMenusOpen = isVisible;
        setNavVisibility(true);
    }

    void setPlayPaused(boolean paused) {
        mPaused = paused;
        mPlayButton.setText(paused ? R.string.play : R.string.pause);
        setKeepScreenOn(!paused);
        setNavVisibility(true);
    }

    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);
    }

}

你如何使用这段代码? - Shajeel Afzal
@steve 我有一个问题,我的活动根布局是RelativeLayout,并且它有一个子视图,设置了android:layout_alignParentBottom="true",导航栏消失了,但子视图没有移动到屏幕底部边缘,就好像导航栏被设置为不可见而不是消失了,你能帮忙吗? - Jack
9个回答

70

从KitKat(4.4.2)开始,有一个名为Immersive Mode的解决方案:https://developer.android.com/training/system-ui/immersive.html

基本上,您应该将以下代码添加到onResume()方法中:

View decorView = getWindow().getDecorView();
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);

4
@radu122 谢谢,但我有一个问题,我的活动根布局是RelativeLayout,并且它有一个子视图,设置了android:layout_alignParentBottom="true",导航栏消失了,但子视图并没有移动到屏幕的底部边缘,就像导航栏被设置为不可见而不是消失了一样,你能帮忙吗? - Jack

26

您可以

两种方法(都需要设备获取root权限):

1- 第一种方法,打开设备的 adb命令窗口,然后运行以下命令:

 adb shell >
 pm disable-user --user 0 com.android.systemui >

要将其重新启用,只需执行相同操作,但将disable更改为enable

第二种方法:将以下行添加到您设备的build.prop文件的末尾:

qemu.hw.mainkeys = 1

要将它取回,只需将其移除即可。

如果您不知道如何编辑 build.prop 文件:

  • 在设备上下载EsExplorer并搜索build.prop,然后更改其权限以进行读写操作,最后添加该行。
  • 下载专用的build.prop编辑器应用程序,例如build.propEditor
  • 或者,请参考此链接

你知道 qemu.hw.mainkeys = 1 是否适用于所有带有软件按钮的设备吗? - JohnyTex
1
@JohnyTex 是的,它很安全,因为它只涉及UI而不涉及系统核心。至于软导航按钮,它们甚至根本不存在,因为它们主要存在于导航栏中。 - Muhammed Refaat
1
这应该是被选择的答案,稍后我会为此答案增加更多的可用性。 - Naveed Ahmad
1
@meditat 是的,都需要 root 权限,我会相应地编辑我的答案。 - Muhammed Refaat
1
我已经删除了之前的评论。方法1适用于Polestar 2模拟器,我不得不重新启动模拟器。 - Shaan_B
显示剩余14条评论

16

您可以隐藏导航栏,只需在onCreate()中调用此方法即可:

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

这将隐藏整个导航面板。希望能对你有所帮助。


1
嗨,有没有办法在Webview中输入焦点后隐藏显示关键字的按钮? - Patrick
笔误?注释应该写//用于更高级的API。 - user1010160
1
@Evish 谢谢,但我有一个问题。我的活动根布局是RelativeLayout,并且它有一个子视图,设置了android:layout_alignParentBottom="true",导航栏消失了,但是子视图没有移动到屏幕底部边缘,就像导航栏被设置为不可见而不是消失了一样。你能帮忙吗?我正在 Android 8.0 设备上进行测试。 - Jack

9
观看了DevBytes视频(由Roman Nurik制作)并阅读文档中的最后一行,其中写道:

注意:如果您喜欢IMMERSIVE_STICKY的自动隐藏行为,但也需要显示自己的UI控件,请使用IMMERSIVE结合Handler.postDelayed()或类似方法在几秒钟后重新进入沉浸模式。

答案是radu122给出的,对我有效。只需设置一个处理程序,就可以正常运行。
以下是对我有效的代码:
@Override
protected void onResume() {
    super.onResume();
    executeDelayed();
}


private void executeDelayed() {
    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            // execute after 500ms
            hideNavBar();
        }
    }, 500);
}


private void hideNavBar() {
    if (Build.VERSION.SDK_INT >= 19) {
        View v = getWindow().getDecorView();
        v.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
这是最糟糕的做法,但谷歌建议这样使用。他们真的不能提供一个更好的方法来解决这个问题吗?太愚蠢了。 - Android Developer
我和你在一起。也许现在平台提供了更好的解决方案。 - Martin Pfeffer
我很抱歉,我目前正在尝试寻找,但是没有任何办法...谷歌在提供真正有用的API方面非常糟糕。 - Android Developer
嗯,在我看来,这个平台非常好且文档十分详细。但是有些功能确实很难实现或者难看,你说得对。 - Martin Pfeffer
@MartinPfeffer 谢谢你,但我有一个问题。我的活动根布局是RelativeLayout,并且它有一个子视图,设置了android:layout_alignParentBottom="true",导航栏消失了,但子视图没有移动到屏幕底部边缘,就好像导航栏被设置为不可见而不是消失了。你能帮忙吗? - Jack
只要没有记录的API可以轻松完成这项工作,这些解决方法就会奏效!如果你想在不root的情况下实现这一点,这是其中一种方法。这是一个非常聪明的答案!它简单地起作用。 - 1111161171159459134

5

更改清单中的主题。

如果您想为某个活动隐藏导航栏,可以使用以下方法:

<activity
        android:name="Activity Name"
        android:theme="@android:style/Theme.Black.NoTitleBar"
        android:label="@string/app_name" >

如果您想为整个应用程序隐藏导航栏,可以使用以下方法:
<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.Black.NoTitleBar" >

3
我想删除导航栏,而不是操作栏。我希望隐藏在平板电脑屏幕底部出现的按钮。 - steve_patrick
1
嗨Steve,这些答案中存在一些阅读理解问题。每个人都想让您删除操作栏。哈哈。您是否曾经弄清楚4.0及以上版本的情况?谢谢。 - steveh

5
据我所知,没有root权限是不可能做到的。如果可以有一个应用程序无法通过系统按钮退出,那将会是一个安全问题。
编辑,请看这里:在平板电脑中隐藏系统栏

4

我的解决方案,只隐藏导航栏,是:

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

    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_HIDE_NAVIGATION
                                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
            }
        }
    });
}

@Override
protected void onResume() {
    super.onResume();
    final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
    final View decorView = getWindow().getDecorView();
    decorView.setSystemUiVisibility(uiOptions);
}

1
你从哪里得到了 getWindow()?在我的端口上它显示:无法读取符号 getWindow()。 - Website Is Fun
1
如果是从片段中调用,请尝试使用 getActivity().getWindow() - Afinas EM

2

在activity的OnResume()方法中开始隐藏,然后按照下面所示继续隐藏:

decorView.setOnSystemUiVisibilityChangeListener
                (new View.OnSystemUiVisibilityChangeListener() {
                    @Override
                    public void onSystemUiVisibilityChange(int visibility) {
                        // Note that system bars will only be "visible" if none of the
                        // LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set.
                        if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                            //visible
                            hideSystemUI();
                        } 
                    }
                    }
                });`

    public 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.
        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 // hide nav bar
                        | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                        | View.SYSTEM_UI_FLAG_IMMERSIVE);
    }

0

来自Google文档:

您可以使用SYSTEM_UI_FLAG_HIDE_NAVIGATION标志在Android 4.0及更高版本上隐藏导航栏。此代码段将隐藏导航栏和状态栏:

View decorView = getWindow().getDecorView();
// Hide both the navigation bar and the status bar.
// SYSTEM_UI_FLAG_FULLSCREEN is only available on Android 4.1 and higher, but as
// a general rule, you should design your app to hide the status bar whenever you
// hide the navigation bar.
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
              | View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);

http://developer.android.com/training/system-ui/navigation.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接