I'm looking at adding a custom view for the HomeAsUpIndicator whenever there are new message. I want to bring attention to the hamburger icon when there are new messages, and then use the default hamburger icon when there aren't new messages.
I have two functions to display custom icon and display default, but I want to use a custom View.
protected void setCustomIcon() {
getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(false);
mDrawerToggle.setDrawerIndicatorEnabled(false);
mDrawerToggle.setHomeAsUpIndicator(R.drawable.ic_menu_hamburger);
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mDrawerLayout.openDrawer(mDrawerList);
}
});
}
protected void setDefaultIcon() {
mDrawerToggle.setDrawerIndicatorEnabled(true);
}
Is there a way to use a custom View instead of a resId or a drawable?
The PlaybackOverlayFragment of the sample app uses the PlaybackControlsGlue to set up playback controls based on the data model. This is the look when using the standard glue:
My problem is that I don't want the title/subtitle text to appear above the main player controls bar - we want them at the top left of the player screen instead. Therefore, to disable the showing of title/subtitle, I override createControlsRowAndPresenter() of the glue and use the empty-args constructor of PlaybackControlsRowPresenter instead:
#Override
public PlaybackControlsRowPresenter createControlsRowAndPresenter() {
PlaybackControlsRow controlsRow = new PlaybackControlsRow(this);
setControlsRow(controlsRow);
final View.OnKeyListener onKeyListener = this;
PlaybackControlsRowPresenter presenter = new PlaybackControlsRowPresenter() { // no AbstractDetailsDescriptionPresenter argument
#Override
protected void onBindRowViewHolder(RowPresenter.ViewHolder vh, Object item) {
super.onBindRowViewHolder(vh, item);
vh.setOnKeyListener(onKeyListener);
}
#Override
protected void onUnbindRowViewHolder(RowPresenter.ViewHolder vh) {
super.onUnbindRowViewHolder(vh);
vh.setOnKeyListener(null);
}
};
// secondaryActionsAdapter setup not shown
presenter.setOnActionClickedListener(new OnActionClickedListener() {
#Override
public void onActionClicked(Action action) {
dispatchAction(action);
}
});
return presenter;
}
The result? No title/subtitle show as expected but now there's more spacing between the primary controls bar and other rows:
What could I be doing wrong, or is it a bug with the leanback library?
Without those two rows of text, the playback controls are now at the top of that view. You can probably apply margins or padding to the playback controls to shift it to the expected location.
Turns out the playback controls need some view above it so they don't occupy the top of their container view (#Nick is right). But I wanted to share my solution in case anyone has a similar need.
PlaybackControlsRowPresenter can take in any presenter in its constructor, not just AbstractDetailsDescriptionPresenters. So createControlsRowAndPresenter() should look like this:
EmojiRowPresenter emojiRowPresenter = new EmojiRowPresenter() {
#Override
protected void onBindEmojiInfo(EmojiRowView rowView, EmojiInfo emojiInfo) {
rowView.setEmojiInfo(emojiInfo);
}
};
PlaybackControlsRowPresenter presenter = new PlaybackControlsRowPresenter(emojiRowPresenter) { // replace the default description presenter with custom presenter
...
}
// everything else stays as before
and EmojiRowPresenter is a subclass of Presenter that looks like this:
public abstract class EmojiRowPresenter extends Presenter {
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
EmojiRowView emojiRowView = new EmojiRowView(parent.getContext());
emojiRowView.setFocusable(true);
emojiRowView.setFocusableInTouchMode(true);
return new ViewHolder(emojiRowView);
}
#Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
EmojiRowView emojiRowView = (EmojiRowView) viewHolder.view;
PlaybackControlHelper glue = (PlaybackControlHelper) item;
EmojiInfo emojiInfo = glue.getEmojiInfo();
if (emojiInfo != null) {
onBindEmojiInfo(emojiRowView, emojiInfo);
}
}
#Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
// ...
}
protected abstract void onBindEmojiInfo(EmojiRowView rowView, EmojiInfo emojiInfo);
}
Of course, EmojiRowView creates the view from the layout that defines each item. Here's the end result:
I've followed Google's official developer tutorials here to create a navigation drawer.
At the moment, everything works fine, except for when the user uses the native back button Android provides at the bottom of the screen (along with the home and recent app buttons). If the user navigates back using this native back button, the navigation drawer will still be open. If the user instead navigates back using the ActionBar, the navigation drawer will be closed like I want it to be.
My code is nearly identical to the official tutorials, except for how I handle the user selecting an item on the drawer:
mDrawerList.setOnItemClickListener(new ListView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView parent, View view, int position, long id)
{
switch(position)
{
case 0:
{
Intent intent = new Intent(MainActivity.this, NextActivity.class);
startActivity(intent);
}
}
}
});
How can I have the navigation drawer be closed when the user navigates back using the native back button? Any advice appreciated. Thanks!
You have to override onBackPressed(). From the docs :
Called when the activity has detected the user's press of the back
key. The default implementation simply finishes the current activity,
but you can override this to do whatever you want.
So you can have code like this :
#Override
public void onBackPressed() {
if (this.drawerLayout.isDrawerOpen(GravityCompat.START)) {
this.drawerLayout.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
If is open this method closes it, else falls back to the default behavior.
You need to override onBackPressed() in your activity and check for the condition where the navigation drawer is open. If it is open, then close it, else do a normal back pressed method. Here is some code mixed with some pseudocode to help you:
#Override
public void onBackPressed(){
if(drawer.isDrawerOpen()){ //replace this with actual function which returns if the drawer is open
drawer.close(); // replace this with actual function which closes drawer
}
else{
super.onBackPressed();
}
}
To replace the pseudocode look in the documentation for the drawer. I know both those methods exist.
Here is an alternative solution to your problem.
#Override
public void onBackPressed(){
if(drawerLayout.isDrawerOpen(navigationView)){
drawerLayout.closeDrawer(navigationView);
}else {
finish();
}
}
UPDATE:
As of support library 24.0.0 this is possible without any workarounds. Two new openDrawer and closeDrawer methods have been added to DrawerLayout that allow the drawer to be opened or closed with no animation.
You can now use openDrawer(drawerView, false) and closeDrawer(drawerView, false) to open and close the drawer with no delay.
If you call startActivity() without calling closeDrawer(), the drawer will be left open in that instance of the activity when you navigate back to it using the back button. Calling closeDrawer() when you call startActivity() has several issues, ranging from choppy animation to a long perceptual delay, depending on which workaround you use. So I agree the best approach is to just call startActivity() and then close the drawer upon return.
To make this work nicely, you need a way to close the drawer without a close animation when navigating back to the activity with the back button. (A relatively wasteful workaround would be to just force the activity to recreate() when navigating back, but it's possible to solve this without doing that.)
You also need to make sure you only close the drawer if you're returning after navigating, and not after an orientation change, but that's easy.
Details
(You can skip past this explanation if you just want to see the code.)
Although calling closeDrawer() from onCreate() will make the drawer start out closed without any animation, the same is not true from onResume(). Calling closeDrawer() from onResume() will close the drawer with an animation that is momentarily visible to the user. DrawerLayout doesn't provide any method to close the drawer without that animation, but it's possible to extend it in order to add one.
Closing the drawer actually just slides it off the screen, so you can effectively skip the animation by moving the drawer directly to its "closed" position. The translation direction will vary according to the gravity (whether it's a left or right drawer), and the exact position depends on the size of the drawer once it's laid out with all its children.
However, simply moving it isn't quite enough, as DrawerLayout keeps some internal state in extended LayoutParams that it uses to know whether the drawer is open. If you just move the drawer off screen, it won't know that it's closed, and that will cause other problems. (For example, the drawer will reappear on the next orientation change.)
Since you're compiling the support library into your app, you can create a class in the android.support.v4.widget package to gain access to its default (package-private) parts, or extend DrawerLayout without copying over any of the other classes it needs. This will also reduce the burden of updating your code with future changes to the support library. (It's always best to insulate your code from implementation details as much as possible.) You can use moveDrawerToOffset() to move the drawer, and set the LayoutParams so it will know that the drawer is closed.
Code
This is the code that'll skip the animation:
// move drawer directly to the closed position
moveDrawerToOffset(drawerView, 0.f);
// set internal state so DrawerLayout knows it's closed
final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
lp.onScreen = 0.f;
lp.knownOpen = false;
invalidate();
Note: if you just call moveDrawerToOffset() without changing the LayoutParams, the drawer will move back to its open position on the next orientation change.
Option 1 (use existing DrawerLayout)
This approach adds a utility class to the support.v4 package to gain access to the package-private parts we need inside DrawerLayout.
Place this class into /src/android/support/v4/widget/:
package android.support.v4.widget;
import android.support.annotation.IntDef;
import android.support.v4.view.GravityCompat;
import android.view.Gravity;
import android.view.View;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class Support4Widget {
/** #hide */
#IntDef({Gravity.LEFT, Gravity.RIGHT, GravityCompat.START, GravityCompat.END})
#Retention(RetentionPolicy.SOURCE)
private #interface EdgeGravity {}
public static void setDrawerClosed(DrawerLayout drawerLayout, #EdgeGravity int gravity) {
final View drawerView = drawerLayout.findDrawerWithGravity(gravity);
if (drawerView == null) {
throw new IllegalArgumentException("No drawer view found with gravity " +
DrawerLayout.gravityToString(gravity));
}
// move drawer directly to the closed position
drawerLayout.moveDrawerToOffset(drawerView, 0.f);
// set internal state so DrawerLayout knows it's closed
final DrawerLayout.LayoutParams lp = (DrawerLayout.LayoutParams) drawerView.getLayoutParams();
lp.onScreen = 0.f;
lp.knownOpen = false;
drawerLayout.invalidate();
}
}
Set a boolean in your activity when you navigate away, indicating the drawer should be closed:
public static final String CLOSE_NAV_DRAWER = "CLOSE_NAV_DRAWER";
private boolean mCloseNavDrawer;
#Override
public void onCreate(Bundle savedInstanceState) {
// ...
if (savedInstanceState != null) {
mCloseNavDrawer = savedInstanceState.getBoolean(CLOSE_NAV_DRAWER);
}
}
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// ...
startActivity(intent);
mCloseNavDrawer = true;
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(CLOSE_NAV_DRAWER, mCloseNavDrawer);
super.onSaveInstanceState(savedInstanceState);
}
...and use the setDrawerClosed() method to shut the drawer in onResume() with no animation:
#Overrid6e
protected void onResume() {
super.onResume();
if(mCloseNavDrawer && mDrawerLayout != null && mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
Support4Widget.setDrawerClosed(mDrawerLayout, GravityCompat.START);
mCloseNavDrawer = false;
}
}
Option 2 (extend from DrawerLayout)
This approach extends DrawerLayout to add a setDrawerClosed() method.
Place this class into /src/android/support/v4/widget/:
package android.support.v4.widget;
import android.content.Context;
import android.support.annotation.IntDef;
import android.support.v4.view.GravityCompat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class CustomDrawerLayout extends DrawerLayout {
/** #hide */
#IntDef({Gravity.LEFT, Gravity.RIGHT, GravityCompat.START, GravityCompat.END})
#Retention(RetentionPolicy.SOURCE)
private #interface EdgeGravity {}
public CustomDrawerLayout(Context context) {
super(context);
}
public CustomDrawerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setDrawerClosed(View drawerView) {
if (!isDrawerView(drawerView)) {
throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
}
// move drawer directly to the closed position
moveDrawerToOffset(drawerView, 0.f);
// set internal state so DrawerLayout knows it's closed
final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
lp.onScreen = 0.f;
lp.knownOpen = false;
invalidate();
}
public void setDrawerClosed(#EdgeGravity int gravity) {
final View drawerView = findDrawerWithGravity(gravity);
if (drawerView == null) {
throw new IllegalArgumentException("No drawer view found with gravity " +
gravityToString(gravity));
}
// move drawer directly to the closed position
moveDrawerToOffset(drawerView, 0.f);
// set internal state so DrawerLayout knows it's closed
final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
lp.onScreen = 0.f;
lp.knownOpen = false;
invalidate();
}
}
Use CustomDrawerLayout instead of DrawerLayout in your activity layouts:
<android.support.v4.widget.CustomDrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
>
...and set a boolean in your activity when you navigate away, indicating the drawer should be closed:
public static final String CLOSE_NAV_DRAWER = "CLOSE_NAV_DRAWER";
private boolean mCloseNavDrawer;
#Override
public void onCreate(Bundle savedInstanceState) {
// ...
if (savedInstanceState != null) {
mCloseNavDrawer = savedInstanceState.getBoolean(CLOSE_NAV_DRAWER);
}
}
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// ...
startActivity(intent);
mCloseNavDrawer = true;
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(CLOSE_NAV_DRAWER, mCloseNavDrawer);
super.onSaveInstanceState(savedInstanceState);
}
...and use the setDrawerClosed() method to shut the drawer in onResume() with no animation:
#Overrid6e
protected void onResume() {
super.onResume();
if(mCloseNavDrawer && mDrawerLayout != null && mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
mDrawerLayout.setDrawerClosed(GravityCompat.START);
mCloseNavDrawer = false;
}
}
Using an implementation of the answer provided by #James Cross worked, but the animation to close the drawer was undesirable and unfixable without much hassle, example.
#Override
public void onResume()
{
super.onResume();
mDrawerLayout.closeDrawers();
}
A work-around is to restart the activity when the device back button is pressed. It does not seem ideal to me, but it works. Overriding onBackPressed(), as suggested by #mt0s and #Qazi Ahmed and passing an extra to determine the calling activity:
mDrawerList.setOnItemClickListener(new ListView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView parent, View view, int position, long id)
{
switch(position)
{
case 0:
{
Intent intent = new Intent(MainActivity.this, NextActivity.class);
//pass int extra to determine calling activity
intent.putExtra(EXTRA_CALLING_ACTIVITY, CallingActivityInterface.MAIN_ACTIVITY);
startActivity(intent);
}
}
}
});
In NextActivity.class, check for the calling activity:
#Override
public void onBackPressed()
{
int callingActivity = getIntent().getIntExtra(EXTRA_CALLING_ACTIVITY, CallingActivityInterface.MAIN_ACTIVITY);
switch(callingActivity)
{
case CallingActivityInterface.MAIN_ACTIVITY:
{
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}
...
}
}
This way the drawer is closed with no animation when I return to MainActivity regardless of whether I use the up button or the back button. There are probably better ways to do this. My app is relatively simple at the moment and this works, but I await a more effective method if anyone has one.
Why the hassle? Simply close the Drawer when clicking a drawer item. That's how it's done in the official Google Play app.
private class DrawerItemClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
drawerLayout.closeDrawer(GravityCompat.START, false);
selectItem(position);
}
}
You will probably want to make sure the navigation draw is always closed when the activity is opened. Use this to do that:
#Override
public void onResume(){
mDrawerList.closeDrawer(Gravity.LEFT);
}
simple sample:
Drawer resultDrawer;
public void onBackPressed(){
if (this.resultDrawer.isDrawerOpen()) {
this.resultDrawer.closeDrawer();
} else {
super.onBackPressed();
}
}
With androidx.drawerlayout:drawerlayout:1.1.0 or higher, you can keep it simple using isOpen and close().
// YourActivity.kt
override fun onBackPressed() {
if (drawerLayout.isOpen) {
drawerLayout.close()
} else {
super.onBackPressed()
}
}
This how i did it:
#Override
public void onBackPressed() {
if(drawerLayout.isDrawerOpen(navigationView)){
drawerLayout.closeDrawer(Gravity.LEFT);
}else{
super.onBackPressed();
}
}
JETPACK COMPOSE
For someone that using jetpack compose.
use this code in your scaffold:
BackHandler(enabled = drawerState.isOpen) {
scope.launch { drawerState.close() }
}
complete version:
val scope = rememberCoroutineScope()
val drawerState = rememberDrawerState(DrawerValue.Closed)
Scaffold(
topBar = {},
bottomBar = {},
snackbarHost = {},
content = {
...
BackHandler(enabled = drawerState.isOpen) {
scope.launch { drawerState.close() }
}
},
...
)
I am using the technique here to animate an activity into life. But I don't want the action bar to show until after the animation is complete. If I set action bar to hide and then to show in onResume, it's as if I never hid it. does anyone know how to do this?
Create an animation and set a callback:
Animation anim = AnimationUtils.loadAnimation(context,R.anim.an_animation);
anim.setAnimationListener(new AnimationListener() {
public void onAnimationEnd() {
// code to show actionbar
}
public void onAnimationStart() {}
public void onAnimationRepeat() {}
}
and then proceed to add the animation to the view and start it
EDIT: I just read you meant to animate an Activity, not a View. Since Activity does not provides any method to set animation callbacks, you could create an AyncTask, in the onCreate method of the second Activity, that will wait the same time as the animation. If the animation goes for 500ms, then your AsyncTask will wait 500ms and then shows the ActionBar:
public class SecondActivity {
private ActionBar bar;
protected void onCreate(Bundle savedInstanceState) {
bar = getActionBar();
bar.hide();
new AsyncTask<Void,Void,Void>() {
#Override
public void doInBackground(Void params...) {
Thread.sleep(500);
bar.show();
return null;
}
}.execute();
}
}
When I create an activity using the fullscreen activity wizard it creatre a fullscreen activity but whenever I click anywhere on the screen the actionbar shows for a few seconds. How can I stop it from doing so?
Full code of FullScreenActivity.java
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*
* #see SystemUiHider
*/
public class FullscreenActivity extends Activity {
/**
* Whether or not the system UI should be auto-hidden after
* {#link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
*/
private static final boolean AUTO_HIDE = true;
/**
* If {#link #AUTO_HIDE} is set, the number of milliseconds to wait after
* user interaction before hiding the system UI.
*/
private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
/**
* If set, will toggle the system UI visibility upon interaction. Otherwise,
* will show the system UI visibility upon interaction.
*/
private static final boolean TOGGLE_ON_CLICK = true;
/**
* The flags to pass to {#link SystemUiHider#getInstance}.
*/
private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;
/**
* The instance of the {#link SystemUiHider} for this activity.
*/
private SystemUiHider mSystemUiHider;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullscreen);
final View controlsView = findViewById(R.id.fullscreen_content_controls);
final View contentView = findViewById(R.id.fullscreen_content);
// Set up an instance of SystemUiHider to control the system UI for
// this activity.
mSystemUiHider = SystemUiHider.getInstance(this, contentView,
HIDER_FLAGS);
mSystemUiHider.setup();
mSystemUiHider
.setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
// Cached values.
int mControlsHeight;
int mShortAnimTime;
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
public void onVisibilityChange(boolean visible) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
// If the ViewPropertyAnimator API is available
// (Honeycomb MR2 and later), use it to animate the
// in-layout UI controls at the bottom of the
// screen.
if (mControlsHeight == 0) {
mControlsHeight = controlsView.getHeight();
}
if (mShortAnimTime == 0) {
mShortAnimTime = getResources().getInteger(
android.R.integer.config_shortAnimTime);
}
controlsView
.animate()
.translationY(visible ? 0 : mControlsHeight)
.setDuration(mShortAnimTime);
} else {
// If the ViewPropertyAnimator APIs aren't
// available, simply show or hide the in-layout UI
// controls.
controlsView.setVisibility(visible ? View.VISIBLE
: View.GONE);
}
if (visible && AUTO_HIDE) {
// Schedule a hide().
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
}
});
// Set up the user interaction to manually show or hide the system UI.
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
}
});
// Upon interacting with UI controls, delay any scheduled hide()
// operations to prevent the jarring behavior of controls going away
// while interacting with the UI.
findViewById(R.id.dummy_button).setOnTouchListener(
mDelayHideTouchListener);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
delayedHide(100);
}
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (AUTO_HIDE) {
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
return false;
}
};
Handler mHideHandler = new Handler();
Runnable mHideRunnable = new Runnable() {
#Override
public void run() {
mSystemUiHider.hide();
}
};
/**
* Schedules a call to hide() in [delay] milliseconds, canceling any
* previously scheduled calls.
*/
private void delayedHide(int delayMillis) {
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, delayMillis);
}
}
if i understand correctly, you just want to hide the action bar?
if yes, Change this line (changing the flag_hide_navigation to 0).
private static final int HIDER_FLAGS = 0;// SystemUiHider.FLAG_HIDE_NAVIGATION;
and add this to the onCreate call:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_ACTION_BAR); //new
getActionBar().hide(); //new
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_fullscreen);
afterwards, if you want to show the action bar, just call from anywhere in the activity :
getActionBar().show();
I Tried The Same By Putting 0 in place of 3000
private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
But its becoming too laggy...
So,The trick u to make changes in androidmanifest.xml
add
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
to AndroidManifest.xml underApplication
This worked for me. Although the navigator isn't removed completely it doesn't allow much time for the user to interact, plus the button icons are small dots. Also this cuts down on the amount of code needed all over the place to make a screen fullscreen.
SystemUiHider hider = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//go full screen with no title
this.requestWindowFeature(Window.FEATURE_PROGRESS); //show progress on loadup
this.requestWindowFeature(Window.FEATURE_NO_TITLE); //hide the title bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //go fullscreen
setContentView(R.layout.activity_main);
//hide the navigation controls
final RelativeLayout mainLayout = (RelativeLayout)this.findViewById(R.id.mainLayout);
hider = SystemUiHider.getInstance(this, mainLayout, SystemUiHider.FLAG_HIDE_NAVIGATION);
hider.setup();
hider.setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
public void onVisibilityChange(boolean visible) {
if (visible) {
//will make navigator into small dots
hider.hide();
//must use delayed to force navigator to disappear completely
final Handler mHideHandler = new Handler();
final Runnable mHideRunnable = new Runnable() {
#Override
public void run() {
hider.hide();
}
};
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, 1000); //min 1 sec to work
}
}
});
hider.hide();
//do the rest of your onCreate stuff here
}
I took a deep look into the code and started the activity on an Android 4.2 device without physical navigation buttons. The default configuration is as fullscreen as possible. It hides status bar, action bar and navigation bar. So how would the user be supposed to get out of your activity if not with a click anywhere on the screen? Anything else would be very restricting and bad usability. I think this is the reason why this behavior can not be manipulated.
What you can do instead, is change the SystemUiHider so that it hides the status bar and the action bar, but not the navigation bar. It instead dimmes the navigation bar to three pale dots, see the screenshot below.
There must be a better way to achieve this, but the following works. Comment these lines in the end of the SystemUiHiderHoneycomb() constructor:
if ((mFlags & FLAG_HIDE_NAVIGATION) != 0) {
// If the client requested hiding navigation, add relevant flags.
mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
mTestFlags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
The activity then stays fullscreen on user interaction and you can toggle() it at a particular event. Of course, you would still have to do the change from my original answer to disable the click behavior.
Original answer:
I guess you have to comment this part:
// Set up the user interaction to manually show or hide the system UI.
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
}
});
In api19 we can use:
getWindow().getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
to hide navigation bar along with status bar
Change the theme of your activity to not have action bar. Best is to inherit from action bar Sherlock activity and remove the action bar
Though its too late to post an answer, but as far as I can understand the question and since I am working using the Full Screen Activity template provided in Android Studio, I think the answer to this question is to disable action bar which becomes visible when the user interacts with the UI, which can be achieved just by disabling the OnClickListener on contentView
i.e.
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
}
});
i.e. comment out the onClick method implementation.
Just comment out
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
By default the state is Off. Toggle happens because there is a onclick listener also added which toggles the screen.
You could simply not add it and delete the code snippet.
The newest code is
// Set up the user interaction to manually show or hide the system UI.
mContentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// toggle();
}
I simply commented out toggle() and voila