NavigationView and ActionBarDrawerToggle - android

With the new NavigationView is it still recommended to use ActionBarDrawerToggle or is this not "Material Design"? For instance previously we were supposed to hide action bar items when the drawer was opened but now the guidelines say that they should stay.

With the new NavigationView is it still recommended to use ActionBarDrawerToggle
No, it's not required.
If you look at the "official" demo code for the new Design Library, ActionBarDrawerToggle is no longer used, since the new NavigationView and AppCompatActivity don't really need it.
With the new v22 support library, you can strip out all of your ActionBarDrawerToggle code and just use the following to handle the interaction between NavigationDrawer and the ActionBar/ToolBar hamburger icon:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
final ActionBar actionBar = getSupportActionBar();
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
actionBar.setDisplayHomeAsUpEnabled(true);
...
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
mDrawerLayout.openDrawer(GravityCompat.START);
return true;
....
}
return super.onOptionsItemSelected(item);
}
You will need to provide your own "hamburger" drawable (R.drawable.ic_menu in my example). Besides that, the above code is all that's needed to handle opening of the drawer. The android.R.id.home case in onOptionsItemSelected() represents your hamburger drawer button. It points to a built-in resource id (not something you add to you menu xml), and it's handled automatically.
Besides that, you have to implement closing of the drawer by simply adding closeDrawers() to your click listener, like this:
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// Handle menu item clicks here.
drawerLayout.closeDrawers();
return true;
}
});
closeDrawers() is a method of DrawerLayout, and takes care of everything. That's it. That's all the code you really need to properly handle navigation drawers now. No more messy code for flipping hamburgers and such!
Of course, if you really want to, you can still use NavigationView with ActionBarDrawerToggle the old way. But you certainly don't have to.
If you want drawer callbacks
Even though ActionBarDrawerToggle is not required to open/close the drawer, it may still be useful for handling additional callbacks (especially if you're using ActionBar already). Otherwise, you can implement your own by using DrawerLayout.DrawerListener or by using DrawerLayout.SimpleDrawerListener(), to handle other open/close related events.

With the new NavigationView is it still recommended to use ActionBarDrawerToggle
Yes. The two tackle two completely different aspects of the navigation drawer.
In total, there are generally three components to a navigation drawer:
A DrawerLayout
Your navigation drawer content
A method of showing and hiding the drawer
The DrawerLayout is the layout that holds the navigation drawer content and your app's content. It is what allows you to pull the drawer in from the side and display the drawer over your app's content (the first child of the DrawerLayout).
Your navigation drawer content (the second child of your DrawerLayout) is typically a list of items that the user can click on. Previously, most implementations that I have seen used a ListView or a RecyclerView and maybe a header of some sort. NavigationView is a replacement for this, and is used to provide Material-compliant drawer contents.
ActionBarDrawerToggle is used to provide the hamburger icon in your app bar. It is what allows your users to tap on the icon to open or close your drawer.

Completing the other answers, the Navigation View should be fit into the whole screen in terms of height so it will hide the hamburger icon when opened. Because of this, having the animation from burger to arrow or even just showing the arrow is not necessary.
But when clicking on the current screen it goes to another fragment, imagine a gallery of photos and clicking on a photo will show it bigger, there should be an animation from burger to arrow and the arrow should stay and when pressed there should be a reverse animation to the burger so the navigation view can be opened again.
You can achieve this with ActionBarDrawerToggle still, even with navigation view because it uses the same DrawerLayout as before. So it still has uses, but of course not necessary.

Related

Why does the android jetpack NavigationUI navigateUp method only open the draw menu if you are at the start destination of the nav graph

When using a NavigationView with a DrawLayout and an ActionBar, jetpack provides some powerful convenience methods to hook everything up together so that these items are easier to implement.
The method setupActionBarWithNavController provided in the NavigationUi library is an extension method for activities that adds a hamburger button to open your drawer and if you override the onSupportNavigateUp:Boolean method on your activity to call navigateUp(drawLayout:DrawLayout, navController:NavController) method, that method will change the hamburger button to a back button and back automatically with a fancy animation, which is super cool.
However it seems that this method is implemented as follows:
public static boolean navigateUp(#Nullable DrawerLayout drawerLayout,
#NonNull NavController navController) {
if (drawerLayout != null && navController.getCurrentDestination().getId()
== navController.getGraph().getStartDestination()) {
drawerLayout.openDrawer(GravityCompat.START);
return true;
} else {
return navController.navigateUp();
}
}
As you can see here, this method has the basic logic of:
if you are not at the start destination of the navgraph, then the button is a back button, otherwise its a hamburger button
This means that only the start destination can open the draw menu via an actionbar button, while all the other destinations have a back button instead, and must swipe to open the draw menu.
Why is this the case? It seems this is a conscious design decision by the android team. Is it frowned upon to have a hamburger button available on multiple destinations?
I would like to have a few main branches that have a hamburger menu and all the screens that branch of from those to have a back button. Is there a way to implement multiple NavGraphs and link them together in one NavigationView?
u_u
I reported a problem I had with the use of a Toolbar inside a fragment and the NavigationUI helper in bug 109868820.
The Googler that helped me indicated clearly (article #7):
[...] the discussions with the material design team has made it clear that the navigation drawer is a global navigation pattern that should be available everywhere
So the material design drawer has to be available on every screen, including the deeper ones when the navigation button is the "up" arrow (not the hamburger). In which case, the drawer is only available from a swipe gesture, as the navigation button navigates up in the app stack.
Indeed (#4 in bug):
You'll still get the title set from the android:label in your navigation graph and proper behavior when it comes to the Up button (particularly important if you're using the DrawerLayout versions)
So the behavior that you found in the source is indeed the "proper" behavior.
Hence:
top level destination: drawer opened through swipe and hamburger button
non-top level destination: drawer opened through swipe only, button navigates up (no hamburger)
In other words, the hamburger button should only be used on top-level destinations.

Navigation View combined with Contextual Action Mode?

New apps from Google, with Material Design, that use a Contextual Action Mode together with a Navigation Drawer.
Starting to swipe the NavigationView in, will temporary hide the ActionMode which will be re-enabled when the drawer is closed again.
In this video: navigation drawer in gmail - look at the toolbar changing because of the navigation drawer swipe.
But how to implement this behavior? The only callback from NavigationView is OnNavigationItemSelected but what we need is maybe a callback from starting to open the drawer and then finishing closing it.
Could other solutions exist, that elude me? For example:
perhaps draw a new toolbar over instead disabling the CAB?
or even is it possible to make the CAB only overlay the Toolbar but not the NavigationView (question still open here?)
I am using:
com.android.support:appcompat-v7:23.4.0
com.android.support:design:23.4.0
android.support.design.widget.NavigationView
android.support.v7.view.ActionMode

Navigation drawer not opening from cutom menu button

I'm working on an Android App, I have a navigation drawer over there. Since the navigation drawer toolbar can't be transparent, and the ending three dots button icon can't be changed, I opted for hiding that toolbar, and show my custom layout. It will give me all the functionality what ever is needed.
But the problem I'm facing right now is, once the activity starts, if I click the custom menu button it doesn't open. Once I drag it and open, after that whenever I click the menu button it opens the navigation drawer.
What might i be missing? This is what I'm doing, while debugging its even coming to the else part, but doesn't open.
In BaseActivity:
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
ivLeft.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (drawer.isDrawerOpen(Gravity.LEFT)) {
drawer.closeDrawer(Gravity.LEFT);
} else {
drawer.openDrawer(Gravity.LEFT);
}
}
});
In any of the child activity:
toolbar.setVisibility(View.GONE);
navigationView.setVisibility(View.GONE);
Please help..
The root cause of your problem is the fact that you're setting the drawer View's visibility to GONE. The direct cause of the odd behavior you describe, though, is due to how DrawerLayout and one of its helper classes update the child Views when the drawer state changes.
The OnClickListener you set to open and close the drawer was working as it should. It just didn't appear to be, since the drawer View was GONE. When you manually opened the drawer by dragging, however, the ViewDragHelper that DrawerLayout uses was firing a callback method that explicitly sets the drawer to VISIBLE. This callback is not fired when the drawer is opened programmatically - that is, with the openDrawer() method - which explains why the drawer didn't show just by clicking your custom toggle button. After you had dragged the drawer open once, the drawer View was visible, and the toggle would then work as expected.
The drawer View is in its closed state by default, so you don't need to hide it, and you can just remove the navigationView.setVisibility(View.GONE); line.

Why same Navigation Drawer is not Toggling from another activity in android?

I want to use same navigation drawer in multiple activities so I have implemented navigation drawer in MainActivity and extended this MainActivity in other Activities in which I want to use the same navigation drawer.
When i Touch the Drawer Icon, it is highlighting but the drawer is not opening.
I have followed the code explained in this link: Same Navigation Drawer on different Activities
Make sure you create your ActionBarDrawerToggle.
I personally do it in Activity.OnCreate() like this:
if (mDrawerLayout != null) {//for large screens it is null
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, 0, 0);
mDrawerLayout.setDrawerListener(this);
}
So in my case I should call super.onCreate() in the descendant class.
Edit
You may also look if all the methods of DrawerListener are overridden correctly.
Still it's not a standard way to use Navigation Drawer. Make sure if your design is what you really need - fragments are more flexible and easy to use. Here is another related post.

Can we launch navigation drawer without using ActionBarDrawerToggle?

Can we launch navigation drawer without using ActionBarDrawerToggle? In my implementation, I do not want to use action bar.
So, I don't want ActionBarDrawerToggle to open and close the drawer. I want to open the navigation drawer when hardware menu button is clicked.
I am targeting Android 2.2 and using support library v4.
As per my understanding, ActionBarDrawerToggle class will have implementation internally to handle the opening and closing of navigation drawer. Am I correct?
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
ImageView ivNavigationIcon = //some image or button or menu what ever you want
ivNavigationIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mDrawerLayout.openDrawer(Gravity.LEFT);
}
});
I want to open the navigation drawer when hardware menu button is clicked
Not every Android device has a MENU button, so you better have some other solution beyond just that.
Also, using MENU to open a navigation drawer, instead of a menu -- may be viewed as odd behavior by some of your users.
I am targeting Android 2.2 and using support library v4.
If you are using DrawerLayout, it has openDrawer() and closeDrawer() methods that you can use that will open the drawer and close the drawer, respectively.

Categories

Resources