我想在我的活动中永久隐藏导航栏(不是整个系统UI)。 现在我正在使用这段代码
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
它隐藏了这个条,但当用户触摸屏幕时它会再次显示。有没有办法永久隐藏它,直到活动onStop()
被调用?
我想在我的活动中永久隐藏导航栏(不是整个系统UI)。 现在我正在使用这段代码
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
它隐藏了这个条,但当用户触摸屏幕时它会再次显示。有没有办法永久隐藏它,直到活动onStop()
被调用?
片段:
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);
}
}
onCreate
中添加的代码,详见setOnSystemUiVisibilityChangeListener。以下是另一个相关问题:Immersive mode navigation becomes sticky after volume press or minimise-restore。java.lang.NullPointerException: Attempt to invoke virtual method 'void com.android.internal.widget.ActionBarContainer.setAlpha(float)' on a null object reference at com.android.internal.app.WindowDecorActionBar.doHide(WindowDecorActionBar.java:822)
- Shajeel Afzalandroid:fitsSystemWindows="true"
。当Android Studio生成某些布局时,它会包含此属性。参见https://dev59.com/O53ha4cB1Zd3GeqPUXCW#42501330。 - Joe Lapp做这个。
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);
}
}
这个方法百分之百有效,而且你可以在较低的API版本中使用同样的方法,即使这是一个晚回答,我希望它能对其他人有所帮助。
如果你想要这个效果一直存在,只需要在你的onResume()
方法中调用FullScreencall()
就可以了。
对于想要更简单解决方案的人,我认为你可以在onStart()
中只有这一行代码。
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION|
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
这被称为沉浸模式。您可以查看官方文档了解其他可能性。
protected void onStart()
{
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION|
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
super.onStart();
}```
- user12500983@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION|View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}
在 public class MainActivity extends ReactActivity
下的 MainActivity.java
中,并导入了 import android.view.View; import android.os.Bundle;
- user5305519尝试使用此方法适用于所有版本的安卓,包括Android 30(R)。
如需了解更多,请查看此类:https://github.com/fiftyonemoon/Rapid/blob/main/rapid/src/main/java/com/fom/rapid/app/UI.java
显示/隐藏所有系统栏:
public void hideSystemUI(Window window) { //pass getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.getInsetsController().hide(WindowInsets.Type.systemBars());
} else {
View decorView = window.getDecorView();
int uiVisibility = decorView.getSystemUiVisibility();
uiVisibility |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
uiVisibility |= View.SYSTEM_UI_FLAG_FULLSCREEN;
uiVisibility |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
uiVisibility |= View.SYSTEM_UI_FLAG_IMMERSIVE;
uiVisibility |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
decorView.setSystemUiVisibility(uiVisibility);
}
}
public void showSystemUI(Window window) { //pass getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.getInsetsController().show(WindowInsets.Type.systemBars());
} else {
View decorView = window.getDecorView();
int uiVisibility = decorView.getSystemUiVisibility();
uiVisibility &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
uiVisibility &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
uiVisibility &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
uiVisibility &= ~View.SYSTEM_UI_FLAG_IMMERSIVE;
uiVisibility &= ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
decorView.setSystemUiVisibility(uiVisibility);
}
}
View
中的setSystemUiVisibility()
方法的标志。然而,自Android 11以来,此API已被弃用。检查我的有关修改系统UI可见性的文章以获取更多信息。该文章还解释了如何正确处理切口或如何监听可见性更改。
这里是使用新API显示/隐藏系统栏以及向后兼容的已弃用的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)
}
}
使用:
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
SYSTEM_UI_FLAG_HIDE_NAVIGATION是一个新标志,可请求完全隐藏导航栏。请注意,这仅适用于某些手机使用的导航栏(它无法隐藏平板电脑上的系统栏)。
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);
}
更多有关此问题的信息,请参见以下内容...
这是我的解决方案:
首先,定义一个布尔变量来指示导航栏是否可见。
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);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
这是一个安全问题: https://dev59.com/kGcs5IYBdhLWcg3wwmnA#12605313
因此,不可能通过一次调用在视图创建的开始永久隐藏平板电脑上的导航。它将被隐藏,但触摸屏幕时它会弹出。因此,只需第二次触摸屏幕即可在您的布局上引发onClickEvent。因此,您需要拦截此调用,但我尚未成功,我将在找到答案后更新我的答案。或者您已经知道答案了吗?