Reputation: 2343
I have been using the flags SYSTEM_UI_FLAG_FULLSCREEN
and SYSTEM_UI_FLAG_HIDE_NAVIGATION
to hide and show both the status and navigation bars. They are working correctly. I am hiding them as the activity starts and I want to show them again on touch event. Android automatically shows them on first touch event (this first touch event is not passed to my app). I'm thinking to use sendMessageDelayed()
to hide both the bars after a certain time. How could I use this first touch event?
Upvotes: 2
Views: 6004
Reputation: 100
-If you want to hide the navigation bar, you will encounter the problem with the first touch event and your app will not be able to do anything with it.
-If you want you can use postDelayed()
to hide the bars after certain time, here is what I have done:
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);
}
}
}
});
}
What we are doing here is:
-First, the navHider
is a Runnable object which is hiding the systemUI.
-Second, the hideSystemUi
method is sets the UI options flags for hiding the status and navigation bar (Note that we are also using LAYOUT_STABLE
Flag so the content would appear behind the status bar and navigation bars and we wont need to resize the content.)
-Third, we are using the systemUIVisibilityChangeListener
, so that after the user interacts with the screen and the status and navigation bars show, we use the postDelayed()
, where the UIVisibility time is the time, you want to wait before we hide the status and navigation bars
You can also show/hide the status bar on every touch event (or clicking a button and etc) We can do this only for the status bar but not for the navigation bar:
/** 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);
}
Note that in those 2 methods: hideSystemUI()
and showSystemUI()
, to avoid the annoying "first touch event" we are using the old pre 4.0 flags, for hiding the status bar.
I am using this code in my ViewPager
(Which I am using to show images), so I can override the onInterceptTouchEvent()
method. Here I check if the system is showing or not, with a simple boolean. Also you need to use MotionEvent.ACTION_UP
, this will allow you to scroll the ViewPager
, without actually showing/hiding the status bar accidentally, so you can scroll in fullscreen mode.
What you can do is make a custom layout (Lets say RelativeLayout
), which extends ViewGroup
and you can overwrite onInterceptTouchEvent
and make this implementation. The touch event will work only on that CustomRelativeLayout
, so if you want for it to work on the whole activity, just make CustomRelativeLayout
your base layout with the match_parent
attributes for height/width.
Here is info for showing and hiding status and navigation bars. https://developer.android.com/training/system-ui/status.html https://developer.android.com/training/system-ui/navigation.html
And this is a link, for managing touch events. https://developer.android.com/training/gestures/viewgroup.html
Upvotes: 0
Reputation: 2343
I got it by using View.OnSystemUiVisibilityChangeListener
. I have just used a Handler.sendMessageDelayed
inside the if condition when both status and navigation bars are visible. See the below implementation for clarity.
Source : 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
}
}
}
});
The disadvantage with this approach is the first touch event could not be used by your app. I think you have to use other approaches like WindowManager.LayoutParams or Immersive Fullscreen Mode in that case.
Upvotes: 7