Switching Between Android Navigation Drawer Image and Up Caret When Using Fragments

Switching between Android Navigation Drawer image and Up caret when using fragments

You have written that, to implement lower-level fragments, you are replacing the existing fragment, as opposed to implementing the lower-level fragment in a new activity.

I would think that you would then have to implement the back functionality manually: when the user pressed back you have code that pops the stack (e.g. in Activity::onBackPressed override). So, wherever you do that, you can reverse the setDrawerIndicatorEnabled.

Switching between activities and fragments in navigation drawer

Have you tried doing the same thing you did with the optionItems and preventing the code related to the fragment to be executed when starting an Activity:

public class BaseDrawerActivity extends AppCompatActivity  {

private DrawerLayout drawerLayout;
private NavigationView nvDrawer;
private ActionBarDrawerToggle actionBarDrawerToggle;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base_drawer);

drawerLayout = findViewById(R.id.drawer);
actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.open, R.string.close);
drawerLayout.addDrawerListener(actionBarDrawerToggle);
actionBarDrawerToggle.syncState();

nvDrawer = findViewById(R.id.nvgView);
// Setup drawer view
setupDrawerContent(nvDrawer);

getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

//Menu created for cart and search icons
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
//return true;
}

//This method is design only for cart and search icons
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();

if(actionBarDrawerToggle.onOptionsItemSelected(item)){
return true;
} else if (id == R.id.cart) {
Intent intent = new Intent(getApplicationContext(), CartActivity.class);
startActivity(intent);
} else if (id == R.id.search) {
Intent intent = new Intent(getApplicationContext(), SearchActivity.class);
startActivity(intent);
}
return super.onOptionsItemSelected(item);
}

//This method is to set up the drawer content/menu
private void setupDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
selectDrawerItem(menuItem);
return true;
}
});
}

public void selectDrawerItem(MenuItem menuItem) {
// Here we create a new fragment and specify the fragment to show based on nav item clicked
Fragment fragment = null;
Class fragmentClass;
switch(menuItem.getItemId()) {
case R.id.nav_home:
fragmentClass = HomeFragment.class;
break;
case R.id.nav_cat:
fragmentClass = CatalogFragment.class;
break;
case R.id.nav_logout:
fragmentClass = CatalogFragment.class;
break;

case R.id.nav_login:
Intent intent = new Intent(getApplicationContext(), OtherActivity.class);
startActivity(intent);
break;
case R.id.nav_profile:
Intent intent = new Intent(getApplicationContext(), ProfileActivity.class);
startActivity(intent);
break;
default:
fragmentClass = HomeFragment.class;
}
//Code related to fragment should not execute when choosing to start an Activity
if(fragmentClass != null){
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}

// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flcontent, fragment).addToBackStack("back tag").commit();

// Highlight the selected item has been done by NavigationView
}
menuItem.setChecked(true);
// Set action bar title
setTitle(menuItem.getTitle());
// Close the navigation drawer
drawerLayout.closeDrawers();
}

}

Android - Navigation Drawer - Fragments overlapping with dynamic meny items

As you mention you have a fragment overlapping problem. I have a solution for that.

XML Part

1) Delete mobile_navigation.xml

2) You need to replace app:navGraph="@navigation/mobile_navigation" with your default fragment name tools:layout="@layout/fragment_home" which is located in content_main.xml file in your case.

Before:

<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/mobile_navigation" />

After:

<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout="@layout/fragment_home" />

MainActivity.java

1) Remove default navigation code

  mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_locations, R.id.nav_settings)
.setOpenableLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);

2) Add custom drawer menu

// set custom toggle menu to open and close drawer
ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
//set menu icon
drawerToggle.setHomeAsUpIndicator(R.drawable.ic_baseline_menu_24);
drawerToggle.setDrawerIndicatorEnabled(false);
drawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawer.openDrawer(GravityCompat.START);
}
});

3) Set default fragment as a home fragment

//set default fragment which will open first
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment,
new HomeFragment()).commit();
}

4) Set NavigationItemSelectedListener

 //set navigation menu item click event
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_home:
getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment,
new HomeFragment()).commit();
drawer.closeDrawers();
break;
case R.id.nav_gallery:
getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment,
new GalleryFragment()).commit();
drawer.closeDrawers();
break;
case R.id.nav_slideshow:
getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment,
new SlideshowFragment()).commit();
drawer.closeDrawers();
break;
default:
break;
}
return true;
}
});

Sample: https://github.com/Vatsal-Dholakiya/navigation_drawer

Sync navigation drawer items with fragments

In your navigation drawer activity , you need to put this method and in every fragments you need to return navigation item index . so it will automatically sync with navigation drawer.

public void NavigationFocus(int navItemIndex) {
navigationView.getMenu().getItem(navItemIndex).setChecked(true);
}

Navigation Drawer to switch activities instead of fragments

Yes it is possible - it's what I did for my app. I already had a number of activities set up, and rather than convert them all to fragments, I wanted to tailor the navigation drawer to work across all of them. Unfortunately, it's not a quick workaround, so if you have the option of using fragments, I would go with that. But regardless here's how I did it:

Let's say I have 2 activities, both of which I want to have the Navigation Drawer. In the layout.xml for each, I specified a DrawerLayout with the appropriate ListView to hold my navigation options. Essentially, the Navigation drawer is made every time I switch between activities, giving the appearance that it is persisting. To make life a lot easier, I took the common methods required to set up the navigation drawer and put them in their own class: NavigationDrawerSetup.java. That way my activities can use the same custom adapter, etc.

Within this NavigationDrawerSetup.java class, I have the following:

  • configureDrawer() - this sets up the ActionBar,
    ActionBarDrawerToggle, and the required listeners
  • My custom array adapter (to populate the navigation options within the list)
  • The selectOptions() method, which handles drawer item clicks

When you set up the navigation drawer within one of your activities, you just create a new NavigationDrawerSetup object and pass in the required layout parameters (like the DrawerLayout, ListView etc). Then you'd call configureDrawer():

        navigationDrawer = new NavigationDrawerSetup(mDrawerView, mDrawerLayout,
mDrawerList, actionBar, mNavOptions, currentActivity);

navigationDrawer.configureDrawer();

currentActivity is passed in since the navigation drawer is tied to the activity you are on. You will have to use it when you set up the ActionBarDrawerToggle:

mDrawerToggle = new ActionBarDrawerToggle(currentActivity, // host Activity
mDrawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description for accessibility */
R.string.drawer_close /* "close drawer" description for accessibility */
)

You will also need to use currentActivity when setting up your custom Adapter:

As for how to switch between activities via the navigation drawer, you can just set up new intents within your selectItem() method:

private void selectItem(int position) {

// Handle Navigation Options
Intent intent;
switch (position) {
case 0:
intent = new Intent(currentActivity, NewActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
currentActivity.startActivity(intent);
break;
case 1:
// etc.
}

Just make sure that your new Activity also has the navigation drawer setup and it should display.

There are a ton of things you can do to customize this method to your own needs, but this is the general structure of how I did it. Hope this helps!



Related Topics



Leave a reply



Submit