Solution 1 :
You have different options:
Just define the SettingsFragment
in your navigation graph:
<navigation xmlns_android="http://schemas.android.com/apk/res/android"
xmlns_app="http://schemas.android.com/apk/res-auto">
<!--Your fragments-->
<!--Settings fragment-->
<fragment
android_id="@+id/settingsFragment"
android_name=".SettingsFragment"/>
</navigation>
Then inflate your menu with:
@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);
return true;
}
In your menu use the same id used in the graph:
<menu xmlns_android="http://schemas.android.com/apk/res/android"
xmlns_app="http://schemas.android.com/apk/res-auto">
<item
android_id="@+id/settingsFragment"
.../>
</menu>
Finally override the onOptionsItemSelected
method:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.onNavDestinationSelected(item, navController)
|| super.onOptionsItemSelected(item);
}
You can also define a Global Action.
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns_android="http://schemas.android.com/apk/res/android"
xmlns_app="http://schemas.android.com/apk/res-auto">
<!--Global action-->
<action android_id="@+id/action_global_open_settings_fragment"
app_destination="@id/settingsFragment"/>
</navigation>
Then in your code to navigate to a destination just use:
Navigation.findNavController(view).navigate(R.id.action_global_open_settings_fragment);
Solution 2 :
I’m not sure if I understand your problem well. But here is my solution and I hope it helps you.
And this is the Code. As you see I’ve an action in SettingsFragment:
<fragment
android_id="@+id/settingsFragment"
android_name="packageName.SettingsFragment"
android_label="Settings Fragment">
<action
android_id="@+id/actionSettingsToPassword"
app_destination="@id/passwordDialogFragment"
app_enterAnim="@anim/fragment_open_enter"
app_exitAnim="@anim/fragment_open_exit" />
And this is my bottomNavigationMenu’s XML:
<item
android_id="@+id/settingsFragment"
android_icon="@drawable/ic_settings"
android_title="Settings" />
Remember that the ID in the Navigation & Menu should be the same. As you see in the codes, the ID of “Settings Fragment” is the same:
android_id="@+id/settingsFragment"
I don’t know if you know how to add preferences.xml in your resources. Just for sure I write it too:
Right Click on “res” New > Android Resource Directory
In the Resource Type field, pickup XML. Now you gonna have xml folder under “res”. Again:
Right Click on “xml” New > XML Recourse File
Now, Here is my “preferences.xml”:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns_android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android_title="Weather Location">
<SwitchPreference
android_defaultValue="true"
android_disableDependentsState="true"
android_key="USE_DEVICE_LOCATION"
android_summary="Allow The App To Get Your Location"
android_title="Use Device Location" />
<EditTextPreference
android_defaultValue="Tehran"
android_dependency="USE_DEVICE_LOCATION"
android_key="CUSTOM_LOCATION"
android_summary="The Location For Which The Weather Is Displayed"
android_title="Location" />
</PreferenceCategory>
<PreferenceCategory android_title="Units">
<ListPreference
android_defaultValue="METRIC"
android_entries="@array/unitSystemEntries"
android_key="UNIT_SYSTEM"
android_summary="%s"
android_title="Unit System"
android_entryValues="@array/unitSystemValues"/>
</PreferenceCategory>
</PreferenceScreen>
Then create a “Kotlin” or “Java” class and set the XML to your class like this (depend on which language are you writing):
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(activity as? AppCompatActivity)?.supportActionBar?.title = "Settings"
(activity as? AppCompatActivity)?.supportActionBar?.subtitle = null
}
}
And here is my Application Class:
class ForecastApplication : Application(){
override fun onCreate() {
super.onCreate()
PreferenceManager.setDefaultValues(this, R.xml.preferences, false)
}
}
and in your application’s Manifest, inside the application tag, define the Application class you already created.
android_name=".ForecastApplication"
I hope this is what you needed.
Problem :
I’m trying to follow this: https://developer.android.com/guide/navigation/navigation-ui along with a review of https://codelabs.developers.google.com/codelabs/android-navigation/#8 (although the second link is in Kotlin and I’m coding in Javascript) to implement an App in Android with navigation drawer on the left and a settings button (preferences) on the top right.
I’m using the NavigationUI with fragments for each option from the drawer and the settings.
My problem is that my settings fragment is not appearing. I think I’m nearly there, but despite reviewing several articles and questions cannot get it to work.
This code allows me to switch fragment from the nav drawer:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
//NavigationUI.setupWithNavController(toolbar, navController, mAppBarConfiguration);
}
If I switch the commented code on the last two lines (so I execute the last line but not second to last), to match the guide then the switching of fragment fails.
My code to handle the Settings menu is:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.onNavDestinationSelected(item, navController)
|| super.onOptionsItemSelected(item);
/*
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
// TODO: Do something to accept settings
View contextView = findViewById(R.id.nav_host_fragment); // Apparently any layout can be used
Snackbar.make(contextView, "Settings", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
//changeFragment(new SettingsFragment());
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.nav_host_fragment, new SettingsFragment(), "nh")
.addToBackStack("nh")
.commit();
return true;
}
return super.onOptionsItemSelected(item);
*/
}
The active portion matches the guide above, is getting called (proved by setting a breakpoint) but doing nothing.
If I alternatively switch this for the commented out code instead, then my settings fragment does appear but overlays the current fragment. I understand from another answer that this is because I am using two different methods to handle fragment visibility, which makes sense and is why I am trying to get my settings fragment to be handled by the NavigationUI framework.
I feel that it must be quite simple to cure, but having read and re-read the guide (and lots of answers cannot make it work)
Comments
Comment posted by A.R.B.N
all I understand is that you want Drawer Layout and Menu in your toolbar, Am I right? and you’re using preferences to setup settings which you came in from Menu in the toolbar, Right? But your settings don’t show up. Right?
Comment posted by PeteC
That sounds right – I might have some of my terms wrong as this is my first app. I have three fragments on the bar that comes in from left (= Drawer Layout?). I have one settings menu (defined as public class SettingsFragment extends PreferenceFragmentCompat along with an associated XML file defining the layout of the seetings). I can’t get the settings to show up using NavigationUI.
Comment posted by A.R.B.N
well try to add your setting fragment or activity in your navigation component, then after implement menu’s onClick, call navigation which you already created in the navigation component. but it’s not good practice to have Drawer and Menu together, One of them is necessary. if you setup drawer and menu, it will be Annoying.
Comment posted by PeteC
Are you suggesting that I should add the Settings menu as another fragment in the drawer? I think you probably are as looking at a few apps on my phone they do have one or the other.
Comment posted by A.R.B.N
No, no. Your setting couldn’t be in your drawer. Look, setting is a new fragment. So you should navigate from current fragment to the settings fragment. For this action, as you said you’re using navigation component, so you should implement the settings fragment in to the navigation component, then in the menu option OR drawer menu, when you click on the settings, you should call navigation action from current fragment to the settings.
Comment posted by schemas.android.com/apk/res/android
I think I already had your option 1 implemented with the exception that I had used different (but identical) name for @+id/settingsFragment in both places and I have no