I am trying to set up proper navigation in my application, which replaces Fragments in a main content area, so I have only one single Activity. I have one main Fragment and several subFragments, for example a Fragment for preferences. Everything works fine when using the back button, but I want to implement the up navigation including icon in addition to this. I am using the ActionBar fetched with Activity.getSupportActionBar() together with a Toolbar from appcompat and an ActionBarDrawerToggle.
I followed this tutorial when setting up my Drawer in the first place.
Current behavior:
When I start the app, the list/drawer icon is shown in the left part of the ActionBar. When I click this, the Drawer opens and I can select items. Sub Fragments are replaced into my content and the back button pops the stack, taking me back to the previous Fragment.
Missing behavior:
The list/drawer icon in the top left is never replaced by the back arrow icon and I cannot figure out how to implement this properly. The Drawer is always pulled out when clicking the list/drawer icon, no matter which Fragment I am in.
What have I tried:
- I tried following this answer. It kinda works, meaning that the back arrow icon is set in the sub
Fragments, but clicking the back arrow still opens theDrawerinstead of providing up navigation. Also, when using the back button to go "up", the list/drawer icon is replaced by nothing. - I also tried following this answer. Here, the desired
ActionBarbehavior/look is implemented in theonCreate()method of the variousFragments. Using this I could get the back arrow up, but still theDraweris pulled when clicking the arrow. - Various other minor things and hacks.
My questions:
- What is wrong in my code below?
- Is it correct/normal to use the combination
ActionBar,ToolbarandActionBarDrawerToggleto implement theDrawernavigation together with up navigation?
MyActivity.onCreate():
@Override
protected void onCreate(Bundle savedInstanceState)
{
// Other stuff
// Setup drawer.
mDrawerFragment = (DrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.mm_navigation_drawer);
mDrawerFragment.initialize(this, (DrawerLayout)findViewById(R.id.mm_drawer_layout), toolbar);
}
DrawerFragment class
public class DrawerFragment extends Fragment
{
private MyActivity mMyActivity;
private MyActionBarDrawerToggle mMyBarDrawerToggle;
private DrawerLayout mDrawerLayout;
private FragmentDrawerListener mFragmentDrawerListener;
private View mContainerView;
public void initialize(MyActivity myActivity, final DrawerLayout drawerLayout, final Toolbar toolbar)
{
mMyActivity = myActivity;
mFragmentDrawerListener = mMyActivity;
mContainerView = myActivity.findViewById(R.id.mm_navigation_drawer);
mMyActionBarDrawerToggle = new MyActionBarDrawerToggle(myActivity, drawerLayout, toolbar, R.string.mm_drawer_open, R.string.mm_drawer_close);
mDrawerLayout = drawerLayout;
mDrawerLayout.setDrawerListener(mMyActionBarDrawerToggle);
mDrawerLayout.post(new Runnable()
{
@Override
public void run()
{
mMyActionBarDrawerToggle.syncState();
}
});
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState)
{
// Not relevant, just create and return the View.
}
}
MyActivity.onDrawerItemSelected()
The implementation of the interface FragmentDrawerListener is done in the MyActivity class. It simply replaces the content area with other Fragments, using FragmentTransactions.
@Override
public void onDrawerItemSelected(View view, int postion)
{
switch (postion)
{
case DrawerAdapter.ITEM_FILTERED_RECIPES:
showFilteredRecipesFragment();
break;
case DrawerAdapter.ITEM_SELECTED_RECIPES:
showSelectedRecipesFragment();
break;
case DrawerAdapter.ITEM_SHOPPING_LIST:
showShoppingListFragment();
break;
case DrawerAdapter.ITEM_SETTINGS:
showSettingsFragment();
break;
case DrawerAdapter.ITEM_ABOUT:
showAboutFragment();
break;
}
}
MyActionBarDrawerToggle class
public class MyActionBarDrawerToggle extends ActionBarDrawerToggle
{
private MyActivity mMyActivity;
private Toolbar mToolbar;
public MyActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, Toolbar toolbar, int openDrawerContentDescRes, int closeDrawerContentDescRes)
{
super(activity, drawerLayout, toolbar, openDrawerContentDescRes, closeDrawerContentDescRes);
mMyActivity = (MyActivity) activity;
mToolbar = toolbar;
}
@Override
public void onDrawerOpened(View drawerView)
{
super.onDrawerOpened(drawerView);
mMyActivity.invalidateOptionsMenu();
}
@Override
public void onDrawerClosed(View drawerView)
{
super.onDrawerClosed(drawerView);
mMyActivity.invalidateOptionsMenu();
}
@Override
public void onDrawerSlide(View drawerView, float slideOffset)
{
super.onDrawerSlide(drawerView, slideOffset);
mToolbar.setAlpha(1 - slideOffset / 2);
}
}
The DrawerFragment is inflated in the main layout using a simple, static Fragment instance like this:
<fragment
android:id="@+id/my_navigation_drawer"
android:name="com.my.company.gui.drawer.DrawerFragment"
android:layout_width="@dimen/my_nav_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
app:layout="@layout/my_drawer_navigation_fragment"
tools:layout="@layout/my_drawer_navigation_fragment">
</fragment>