如何在第一次触摸事件后隐藏状态和导航栏?
How to hide status and navigation bars after first touch event?
我一直在使用标志 SYSTEM_UI_FLAG_FULLSCREEN
和 SYSTEM_UI_FLAG_HIDE_NAVIGATION
来隐藏和显示状态栏和导航栏。他们工作正常。我在 activity 开始时隐藏它们,我想在触摸事件中再次显示它们。 Android 在第一次触摸事件时自动显示它们(第一次触摸事件没有传递到我的应用程序)。我正在考虑使用 sendMessageDelayed()
在一定时间后隐藏两个栏。我怎么能使用这个第一次触摸事件?
-如果你想隐藏导航栏,你会遇到第一个触摸事件的问题,你的应用程序将无法对其进行任何操作。
-如果你愿意,你可以使用 postDelayed()
在一定时间后隐藏条形图,这是我所做的:
Runnable navHider = new Runnable() {
@Override
public void run() {
Log.e("HIDING", "hide");
hideSystemUi();
}
/** Hides StatusBar and NavigationBar */
private void hideSystemUi() {
if (isLandscape()) {
// Set flags for hiding status bar and navigation bar
View decorView = ((Activity) context).getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
}
}
private void setVisibilityChangeListener() {
View decorView = ((Activity) context).getWindow().getDecorView();
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 (isLandscape()) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
getHandler().postDelayed(navHider,
UI_VISIBILITY_TIME);
}
}
}
});
}
我们在这里做的是:
-首先,navHider
是一个隐藏系统的 Runnable 对象UI。
-其次,hideSystemUi
方法设置 UI 选项标志用于隐藏状态和导航栏(请注意,我们还使用 LAYOUT_STABLE
标志,因此内容会出现在状态栏和导航栏后面,我们不需要调整内容的大小。)
-第三,我们正在使用systemUIVisibilityChangeListener
,这样在用户与屏幕交互并且状态和导航栏显示后,我们使用postDelayed()
,其中UIVisibility time就是时间,你要等我们隐藏状态和导航栏
您还可以 show/hide 每个触摸事件(或单击按钮等)的状态栏我们只能对状态栏执行此操作,但不能对导航栏执行此操作:
/** Hides StatusBar and NavigationBar */
private void hideSystemUi() {
if (isLandscape()) {
// Set flags for hiding status bar and navigation bar
View decorView = ((Activity) context).getWindow().getDecorView();
// // Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
Window window = ((Activity) context).getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
((Activity) context).getActionBar().hide();
isShowing = false;
}
}
private void showSystemUi() {
View decorView = ((Activity) context).getWindow().getDecorView();
Window window = ((Activity) context).getWindow();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
((Activity) context).getActionBar().show();
isShowing = true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (isShowing) {
Log.e("onInterceptTouchEvent", "Hiding System UI");
hideSystemUi();
} else {
Log.e("onInterceptTouchEvent", "Showing System UI");
showSystemUi();
}
}
return super.onInterceptTouchEvent(event);
}
请注意,在这两种方法中:hideSystemUI()
和 showSystemUI()
,为了避免烦人的 "first touch event" 我们使用旧的 pre 4.0 标志来隐藏状态栏。
我在 ViewPager
(我用来显示图像)中使用此代码,因此我可以覆盖 onInterceptTouchEvent()
方法。在这里,我使用一个简单的布尔值检查系统是否正在显示。此外,您还需要使用 MotionEvent.ACTION_UP
,这将允许您滚动 ViewPager
,而不会意外 showing/hiding 状态栏,因此您可以在全屏模式下滚动。
您可以做一个自定义布局(比方说 RelativeLayout
),它扩展了 ViewGroup
,您可以覆盖 onInterceptTouchEvent
并进行此实现。触摸事件将仅在 CustomRelativeLayout
上起作用,因此如果您希望它在整个 activity 上起作用,只需将 CustomRelativeLayout
设置为具有 match_parent
属性的基本布局height/width.
这里是显示和隐藏状态栏和导航栏的信息。
https://developer.android.com/training/system-ui/status.html
https://developer.android.com/training/system-ui/navigation.html
这是一个link,用于管理触摸事件。
https://developer.android.com/training/gestures/viewgroup.html
我是用View.OnSystemUiVisibilityChangeListener
得到的。当状态栏和导航栏都可见时,我刚刚在 if 条件中使用了 Handler.sendMessageDelayed
。为清楚起见,请参阅下面的实现。
来源:Responding to UI Visibility Changes
View decorView = getActivity().getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {@Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
// TODO: The system bars are visible. Make any desired
Message msg = mHandler.obtainMessage(HIDE_STATUSBAR); //Implement your hide functionality accordingly
mHandler.sendMessageDelayed(msg, 3000);
} else {
// TODO: The system bars are NOT visible. Make any desired
}
}
}
});
这种方法的缺点是您的应用无法使用第一个触摸事件。我认为在这种情况下您必须使用其他方法,例如 WindowManager.LayoutParams or Immersive Fullscreen Mode。
我一直在使用标志 SYSTEM_UI_FLAG_FULLSCREEN
和 SYSTEM_UI_FLAG_HIDE_NAVIGATION
来隐藏和显示状态栏和导航栏。他们工作正常。我在 activity 开始时隐藏它们,我想在触摸事件中再次显示它们。 Android 在第一次触摸事件时自动显示它们(第一次触摸事件没有传递到我的应用程序)。我正在考虑使用 sendMessageDelayed()
在一定时间后隐藏两个栏。我怎么能使用这个第一次触摸事件?
-如果你想隐藏导航栏,你会遇到第一个触摸事件的问题,你的应用程序将无法对其进行任何操作。
-如果你愿意,你可以使用 postDelayed()
在一定时间后隐藏条形图,这是我所做的:
Runnable navHider = new Runnable() {
@Override
public void run() {
Log.e("HIDING", "hide");
hideSystemUi();
}
/** Hides StatusBar and NavigationBar */
private void hideSystemUi() {
if (isLandscape()) {
// Set flags for hiding status bar and navigation bar
View decorView = ((Activity) context).getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
}
}
private void setVisibilityChangeListener() {
View decorView = ((Activity) context).getWindow().getDecorView();
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 (isLandscape()) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
getHandler().postDelayed(navHider,
UI_VISIBILITY_TIME);
}
}
}
});
}
我们在这里做的是:
-首先,navHider
是一个隐藏系统的 Runnable 对象UI。
-其次,hideSystemUi
方法设置 UI 选项标志用于隐藏状态和导航栏(请注意,我们还使用 LAYOUT_STABLE
标志,因此内容会出现在状态栏和导航栏后面,我们不需要调整内容的大小。)
-第三,我们正在使用systemUIVisibilityChangeListener
,这样在用户与屏幕交互并且状态和导航栏显示后,我们使用postDelayed()
,其中UIVisibility time就是时间,你要等我们隐藏状态和导航栏
您还可以 show/hide 每个触摸事件(或单击按钮等)的状态栏我们只能对状态栏执行此操作,但不能对导航栏执行此操作:
/** Hides StatusBar and NavigationBar */
private void hideSystemUi() {
if (isLandscape()) {
// Set flags for hiding status bar and navigation bar
View decorView = ((Activity) context).getWindow().getDecorView();
// // Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
Window window = ((Activity) context).getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
((Activity) context).getActionBar().hide();
isShowing = false;
}
}
private void showSystemUi() {
View decorView = ((Activity) context).getWindow().getDecorView();
Window window = ((Activity) context).getWindow();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
((Activity) context).getActionBar().show();
isShowing = true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (isShowing) {
Log.e("onInterceptTouchEvent", "Hiding System UI");
hideSystemUi();
} else {
Log.e("onInterceptTouchEvent", "Showing System UI");
showSystemUi();
}
}
return super.onInterceptTouchEvent(event);
}
请注意,在这两种方法中:hideSystemUI()
和 showSystemUI()
,为了避免烦人的 "first touch event" 我们使用旧的 pre 4.0 标志来隐藏状态栏。
我在 ViewPager
(我用来显示图像)中使用此代码,因此我可以覆盖 onInterceptTouchEvent()
方法。在这里,我使用一个简单的布尔值检查系统是否正在显示。此外,您还需要使用 MotionEvent.ACTION_UP
,这将允许您滚动 ViewPager
,而不会意外 showing/hiding 状态栏,因此您可以在全屏模式下滚动。
您可以做一个自定义布局(比方说 RelativeLayout
),它扩展了 ViewGroup
,您可以覆盖 onInterceptTouchEvent
并进行此实现。触摸事件将仅在 CustomRelativeLayout
上起作用,因此如果您希望它在整个 activity 上起作用,只需将 CustomRelativeLayout
设置为具有 match_parent
属性的基本布局height/width.
这里是显示和隐藏状态栏和导航栏的信息。 https://developer.android.com/training/system-ui/status.html https://developer.android.com/training/system-ui/navigation.html
这是一个link,用于管理触摸事件。 https://developer.android.com/training/gestures/viewgroup.html
我是用View.OnSystemUiVisibilityChangeListener
得到的。当状态栏和导航栏都可见时,我刚刚在 if 条件中使用了 Handler.sendMessageDelayed
。为清楚起见,请参阅下面的实现。
来源:Responding to UI Visibility Changes
View decorView = getActivity().getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {@Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
// TODO: The system bars are visible. Make any desired
Message msg = mHandler.obtainMessage(HIDE_STATUSBAR); //Implement your hide functionality accordingly
mHandler.sendMessageDelayed(msg, 3000);
} else {
// TODO: The system bars are NOT visible. Make any desired
}
}
}
});
这种方法的缺点是您的应用无法使用第一个触摸事件。我认为在这种情况下您必须使用其他方法,例如 WindowManager.LayoutParams or Immersive Fullscreen Mode。