Navigation drawer buttons are not working [duplicate] - java

I am working on an app with a side Navigation drawer. The drawer opens fine, however the text that supposedly can be "clickable" does not seem to respond. The animation shows that there is feedback to when the drawer is tapped (you can hear the sound) however nothing results of it. I have tried to place toast messages to see if the button registers an action, but when pressed, no toast appears.
The code goes as follows (I have implemented NavigationView.OnNavigationItemSelectedListener):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_driver_home);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_history, R.id.nav_settings,
R.id.nav_help, R.id.nav_signout)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
And then I implemented the method:
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.nav_history:
Toast.makeText(this, "fsdfuxc", Toast.LENGTH_LONG).show();
break;
case R.id.nav_help:
break;
case R.id.nav_settings:
break;
case R.id.nav_signout:
signOut();
break;
}
DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
Thank you

The line
NavigationUI.setupWithNavController(navigationView, navController);
Calls setNavigationItemSelectedListener internally to connect destinations to menu items (i.e., when you click on the R.id.nav_settings MenuItem, it'll replace the Fragment in your NavHostFragment with the one with android:id="#+id/nav_settings" set). This listener overrides the OnNavigationItemSelectedListener view you've set, which is why your custom logic doesn't run.
If you want to combine both sets of functionality together, you need to call navigationView.setNavigationItemSelectedListener(this); after setupWithNavController and trigger the default behavior with NavigationUI.onNavDestinationSelected():
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_driver_home);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_history, R.id.nav_settings,
R.id.nav_help, R.id.nav_signout)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
// This line needs to be after setupWithNavController()
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
switch (menuItem.getItemId()){
case R.id.nav_history:
Toast.makeText(this, "fsdfuxc", Toast.LENGTH_LONG).show();
break;
case R.id.nav_signout:
signOut();
break;
default:
// Trigger the default action of replacing the current
// screen with the one matching the MenuItem's ID
NavigationUI.onNavDestinationSelected(menuItem, navController);
}
DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}

Just a small sample based on the accepted answer but inside the fragment, without overriding the annotation and using Kotlin.
bottomNav.setOnNavigationItemSelectedListener {
when (it.itemId) {
R.id.share -> {
shareViaWhatsApp()
}
else -> {
NavigationUI.onNavDestinationSelected(it, navController!!)
}
}
true
}

Related

Android horizontal and vertical slide

i have one big problem i am a beginner and i don't know how to implement horizontal and vertical slide between fragments, i have around 100 main and 100 additional fragments for each of that fragment.
Can someone please explain to me the simplest way.
https://i.stack.imgur.com/5WHhD.png
My code :
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
private ActivityMainBinding binding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.appBarMain.toolbar);
DrawerLayout drawer = binding.drawerLayout;
NavigationView navigationView = binding.navView;
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav01, R.id.nav02, R.id.nav03, R.id.nav04, R.id.nav05, R.id.nav06, R.id.nav07, R.id.nav08, R.id.nav09
, R.id.nav10, R.id.nav11, R.id.nav12, R.id.nav13, R.id.nav14, R.id.nav15, R.id.nav16, R.id.nav17, R.id.nav18, R.id.nav19, R.id.nav20, R.id.nav21
, R.id.nav22, R.id.nav23, R.id.nav24, R.id.nav25, R.id.nav26, R.id.nav27, R.id.nav28, R.id.nav29, R.id.nav30, R.id.nav31, R.id.nav32, R.id.nav33,
R.id.nav34, R.id.nav35, R.id.nav36, R.id.nav37, R.id.nav38, R.id.nav39, R.id.nav40, R.id.nav41, R.id.nav42, R.id.nav43, R.id.nav44, R.id.nav45,
R.id.nav46, R.id.nav47, R.id.nav48, R.id.nav49, R.id.nav50, R.id.nav51, R.id.nav52, R.id.nav53, R.id.nav54, R.id.nav55, R.id.nav56, R.id.nav57,
R.id.nav58, R.id.nav59, R.id.nav60, R.id.nav61, R.id.nav62, R.id.nav63, R.id.nav64, R.id.nav65, R.id.nav66, R.id.nav67, R.id.nav68, R.id.nav69,
R.id.nav70, R.id.nav71, R.id.nav72, R.id.nav73, R.id.nav74, R.id.nav75, R.id.nav76, R.id.nav77,R.id.nav78,R.id.nav79,R.id.nav80,R.id.nav81,R.id.nav82,
R.id.nav83,R.id.nav84, R.id.nav85, R.id.nav86,R.id.nav87,R.id.nav88,R.id.nav89,R.id.nav90,R.id.nav91,R.id.nav92,R.id.nav93,R.id.nav94,R.id.nav95,R.id.nav96,
R.id.nav97,R.id.nav98,R.id.nav99
)
.setOpenableLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
}

Saving Fragment state with Android BottomNavigation

I'm new to Android development, so I do not understand many, perhaps elementary things, perhaps even the stated topic does not fully reflect my questions, I apologize in advance, I could not formulate more precisely. Please help me with some questions.
I have a BottomNavigation in my application with three menu items. Like on a picture:
bottom nav
Initially, I did it as in the standard Android Studio example:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private NavController navController;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
BottomNavigationView navView = findViewById(R.id.nav_view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_update, R.id.navigation_notifications)
.build();
navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(binding.navView, navController);
}
}
In this code, the menu items switch fragments, saving the state of each of them (I don’t know how exactly, it seems to be somewhere inside the navigation controller).
But now I needed the middle button to perform a different function, i.e. not to participate in switching fragments.
The only adequate way to do this is to use setOnItemSelectedListener.
Then my code will look like this:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private NavController navController;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
BottomNavigationView navView = findViewById(R.id.nav_view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_update, R.id.navigation_notifications)
.build();
navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(binding.navView, navController);
navView.setOnItemSelectedListener(
new NavigationBarView.OnItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
navController.navigate(R.id.navigation_home);
break;
case R.id.navigation_update:
// work for middle menu item
break;
case R.id.navigation_notifications:
navController.navigate(R.id.navigation_notifications, savedInstanceState);
break;
}
return true;
}
});
}
}
It even works, except that the fragments no longer save their state. That is, for example, in the first fragment I have a RecyclerView, if I scroll it down, switch to another fragment, and then return back, then the RecyclerView is in the default state (not scrolled), that is the state has not been saved.
It turns out that in the first version of the code I can’t do individual work with the middle menu item, and in the second version the states of the fragments are not saved.
Prompt correct way to deal with this problem. So that the middle menu item can be assigned a separate job, and the state of the fragments can be saved.
instead of using navView.setOnItemClickListener, you can use navController.addOnDestinationChangedListener, and in overrided onDestinationChanged method, you can check
if(destination.id == R.id.navigation_update) {
//your custom action here
}
I was able to solve the problem with standard tools using Navigation.
I just found a menu item and added a OnClickListener to it.
BottomNavigationItemView updateBtn = findViewById(R.id.navigation_update);
updateBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// todo
}
});
Thus, both switching fragments and clicking on the middle menu item work correctly.

How do I stop AppBarConfiguration from switching the hamburger icon into the back arrow?

How do I get the hamburger icon back for the navigation drawer? the AppBarConfiguration changes it into a back arrow, why is that?
This is my code below:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
init_v3();
BottomNavigationView navView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(R.id.home, R.id.nav_tasks)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
}
You should add all the fragments that you don't want the up/back button to show up in the appBarConfiguration
In your example, this up/back button won't show up in R.id.nav_tasks & R.id.home fragments as you already added them. >> if you have more fragments, then add them into the below separating between them with comma.
And to show up the Drawer burger icon, you need to call setOpenableLayout(drawerLayout)
DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.home,
R.id.nav_tasks)
.setOpenableLayout(drawerLayout)
.build();

Android NavigationComponent: Navigation Drawer not reacting

I am trying to use the new Navigation components from Android jetpack to create a navigation drawer. For some reason, the corresponding burger button does show up on the screen but doesn't react to clicks at all.
I've tried several tutorials online but to no avail. The last thing I tried was the offcial approach from https://developer.android.com/guide/navigation/navigation-ui.
MainActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupNavigation();
}
private void setupNavigation() {
drawer = findViewById(R.id.drawer_layout);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
navController = Navigation.findNavController(this, R.id.nav_host_fragment);
AppBarConfiguration appBarConfiguration =
new AppBarConfiguration.Builder(navController.getGraph())
.setDrawerLayout(drawer)
.build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationView navView = findViewById(R.id.nav_view);
NavigationUI.setupWithNavController(navView, navController);
}
I don't understand why it isn't reacting to clicks at all.
As per the ActionBar section of that same page:
Next, override onSupportNavigateUp() to handle Up navigation:
override fun onSupportNavigateUp(): Boolean {
return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp()
}
Note that the AppBarConfiguration you create will need to be a variable at the class level as well so it can be used in both setupNavigation() and onSupportNavigateUp().

NavigationView click event

I am using the android navigation drawer navigation menu from the Android Studio template. How do I navigate to the different activity based on the id.
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow,
R.id.nav_tools, R.id.nav_share, R.id.nav_send)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.admin_panel_navigation, menu);
return true;
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.onNavDestinationSelected(item, navController)
|| super.onOptionsItemSelected(item);
}
I tried the below set of codes, but it doesn't perform the click operation.
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
// Handle navigation view item clicks here.
switch (item.getItemId()) {
case R.id.nav_maths: {
//do somthing
break;
}
}
//close navigation drawer
mDrawerLayout.closeDrawer(GravityCompat.START);
return true;
}
I know I am missing something, but I am not able to find the solution. Can anyone please help me.
As per the Tie destinations to menu items section, Navigation uses the IDs you add to your menu xml, matching them to destinations in your navigation graph xml file.
So if you had a menu item such as
<item
android:id="#+id/nav_maths"
android:icon="#drawable/maths"
android:title="#string/maths" />
and wanted it to start a different activity, you could add an <activity> destination to your navigation graph:
<activity
android:id="#+id/nav_maths"
android:name="com.your.package.MathsActivity" />
And because they have the same ID, your activity would be started when you click that item in your menu.
Note that Navigation focuses on having just a single activity, so an activity destination should be considered an exit point from your graph - your second activity would have its own navigation graph, etc. that is completely separate from the first one.

Categories