So I am using https://github.com/neokree/MaterialNavigationDrawer for my navigation drawer and https://gist.github.com/Jogan/9def6110edf3247825c9 as my FAB implementation. When I open the navigation drawer, it does not cover the FAB, and the button appears on top of it. I would like to avoid hiding the button and showing it on drawer open/close as that is rather distracting. Any ideas on how to fix this?
Edit:
I am adding the FAB programmatically doing the following:
fabButton = new FloatingActionButton.Builder(this)
.withDrawable(getResources().getDrawable(R.drawable.ic_action_edit))
.withButtonColor(0xFF2196F3)
.withGravity(Gravity.BOTTOM | Gravity.END)
.withMargins(0, 0, 16, 16)
.create();
Changing that declaration to the fragment does not fix it. The Nav Bar implementation I linked above requires the activity to extend from a MaterialNavigationDrawer class, which may draw the Nav Drawer first, leaving the button to always be last. Is there any way to programmatically force the ordering of the elements?
You see FAB when the navigation drawer is open because this FAB implementation adds FAB to the content view (android.R.id.content
). Depending on the navigation drawer implementation they seem to be on same level in the view hierarchy.
If you don't want to switch to different FAB implementation. Use onDrawerSlide(View drawerView, float offset)
and change FAB alpha as you open the drawer. Also you could toggle its visibility inside onDrawerClose()
or onDrawerOpen()
methods too.
Edit:
@Override
public void onDrawerSlide(View drawerView, float offset){
fabButton.setAlpha(offset);
}
I've found a neat solution that doesn't involve alpha in it or toggling the button when the drawer's opened or closed (which makes it look like a delay). Programmatically, you can modify the button's end margin so that it transitions out of the activity's window while the drawer's offset changes.
So first of all, outside the onDrawerSlide
method, you must get the FAB's layout parameters with the following code (depending on the layout the button's in, in my case, it's a FrameLayout
):
final FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) fab.getLayoutParams();
Understand that I'm doing this based on a simple mathematical linear equation: y = mx + n, while 'y' is the margin, 'm' is the slope (you can modify it), 'x' is the slideOffset
and 'n' is the default/original margin (16dp). This is how you assign the default margin and the slope to variables as pixels while respecting the abundance of display densities:
int density = (int) Resources.getSystem().getDisplayMetrics().density;
final int defaultMargin = 16 * density;
final int slope = -100 * density;
Then, inside onDrawerSlide
, do the following:
params.setMarginEnd((int) (slope * slideOffset + defaultMargin));
fab.setLayoutParams(params);
If this doesn't work for you, try to set the button's marginEnd
when building it, or set the margins of the layout's parameters like this (though you would have to check if marginEnd
is right or left):
params.setMargins(int left, int top, int right, int bottom);
I hope this helped. This is my first answer so I hope you won't have much complaints about it.
This is an alternative solution which works for me.
Suppose you want to add FAB in yourlayout.xml.
Now create a framelayout in yourlayout.xml
<FrameLayout
android:id="@+id/myframelayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
Now in FloatingActionButton.java replace the method
public FloatingActionButton create() {
...
ViewGroup root = (ViewGroup) activity.findViewById(android.R.id.content);
root.addView(button, params);
return button;
}
with
public FloatingActionButton create(FrameLayout framelayout) {
...
framelayout.addView(button, params);
return button;
}
Now change the FAB declaration like this.
FrameLayout yourframelayout = (FrameLayout)findViewById(R.id.myframelayout);
fabButton = new FloatingActionButton.Builder(this)
.withDrawable(getResources().getDrawable(R.drawable.ic_action_edit))
.withButtonColor(0xFF2196F3)
.withGravity(Gravity.BOTTOM | Gravity.END)
.withMargins(0, 0, 16, 16)
.create(yourframelayout);
That's it!!
I am updating Nikola Despotoski solution:
So you have to disable/hide the fab also after setting the alpha so if any time user taps at place where fab is shown then nothing would happen.
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.drawer_open,
R.string.drawer_close) {
public void onDrawerClosed(View view) {
// Visible/Enable the FAB
}
public void onDrawerOpened(View drawerView) {
// Hide/Disable the FAB
}
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
// invert the slideOffset value
fab.setAlpha(1-slideOffset);
}
};