I am trying to set up proper navigation in my application, which replaces Fragment
s 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 Fragment
s 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
Fragment
s, but clicking the back arrow still opens theDrawer
instead 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
ActionBar
behavior/look is implemented in theonCreate()
method of the variousFragment
s. Using this I could get the back arrow up, but still theDrawer
is 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
,Toolbar
andActionBarDrawerToggle
to implement theDrawer
navigation 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 Fragment
s, using FragmentTransaction
s.
@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>