Reputation: 55
I'm trying to change current fragment when user clicks the menu in toolbar using navigation components, however I can't get the menu to work from fragment at all! I'm using bottom navigation bar with 2 fragments and each fragment has different toolbar menu items, I'm not using navigation drawer. Here's a little snippet from HomeFragment.kt:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
activity?.title = getString(R.string.title_home)
setHasOptionsMenu(true)
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.toolbar_menu, menu)
super .onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.toolbar_about -> {
activity?.findNavController(R.id.bottom_nav_host)?.navigate(R.id.toAboutFragment)
Toast.makeText(context, "You clicked on About menu", Toast.LENGTH_SHORT).show()
}
else -> super.onOptionsItemSelected(item)
}
return true
}
It doesn't even display the Toast that I specified. Could anyone help me? Thanks in advance!
Upvotes: 1
Views: 1705
Reputation: 349
There are several things that might be checked
1)Styles App Themes
<resources>
<style name="AppThem
parent="Theme.AppCompat.Light.DarkActionBar"> .....
the fragment code does not work unless the main activity is set to support the action bar in the fragment. It took me a while to understand this....
class MainActivity : AppCompatActivity() {
private var currentNavController: LiveData<NavController>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
setupBottomNavigationBar()}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
setupBottomNavigationBar()
}
private fun setupBottomNavigationBar() {
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
val navGraphIds = listOf(R.navigation.signin, R.navigation.register, R.navigation.elections_list)
val controller = bottomNavigationView.setupWithNavController(
navGraphIds = navGraphIds,
fragmentManager = supportFragmentManager,
containerId = R.id.nav_host_container,
intent = intent
)
controller.observe(this, Observer { navController ->
setupActionBarWithNavController(navController) })
currentNavController = controller
}
override fun onSupportNavigateUp(): Boolean {
return currentNavController?.value?.navigateUp() ?: false
}
companion object
}
Menu code
<menu
android:id="@+id/menu_collections_new"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/men_item1"
android:icon="@drawable/ic_icon"
android:title="item1"
app:showAsAction="ifRoom"/>
<item android:id="@+id/men_item2"
app:showAsAction="never"
android:title="item2"
/>
<item android:id="@+id/men_item3"
android:title="item3"
app:showAsAction="never">
<menu>
<item
android:id="@+id/subitem1"
android:title="Subitem1"/>
<item
android:id="@+id/subitem2"
android:title="Subitem2"/>
</menu>
</item>
</menu>
FRAGMENT CODE set up the proper code in the actual fragment FragmentOne.kt NOTE super.onCreateOptionsMenu(menu, inflater) AND inflater.inflate(R.menu.menu_collections_new, menu)
override fun onCreate(savedInstanceState: Bundle?) { setHasOptionsMenu(true) super.onCreate(savedInstanceState) }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_collections_new, menu)
super.onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.men_item1-> onSignOutClicked( "item1")
R.id.men_item2 -> onSignOutClicked("item2")
R.id.men_item3 ->onSignOutClicked("item3")
}
return super.onOptionsItemSelected(item)
private fun onSignOutClicked(description:String) {
Log.d(TAG,"dja 193 options menu selected $description")
}
Upvotes: 0
Reputation: 55
I managed to fix this by calling onOptionsItemSelected
directly from activity instead of fragment. So my final code looks like this:
HomeFragment.kt
:
//We set menu from fragment
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.toolbar_menu, menu)
super .onCreateOptionsMenu(menu, inflater)
}
MainActivity.kt
:
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val navHost = findNavController(R.id.bottom_nav_host)
when (item.itemId) {
android.R.id.home -> {
onBackPressed()
return true
}
//This one is for our fragment toolbar menu
R.id.toolbar_about -> {
navHost.navigate(R.id.toAboutFragment)
return true
}
}
return false
}
Upvotes: 0
Reputation: 137
You can open menu on your host Activity. If you wanna open it on Fragment, you can use context. Check the below code.
public class FragmentEditProfile extends Fragment {
Context m_context; //Context
public static FragmentEditProfile newInstance() {
return new FragmentEditProfile();
}
@Override
public void onCreate(Bundle savedInstanceState) {
// Get context of host activity.
m_context = getContext();
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragmentLayout = inflater.inflate(R.layout.fragment_profile_edit, container, false);
// setNavigationOnClickListener of the host activity.
((MainActivity)m_context).toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Open the menu using context of host activity
((MainActivity) m_context).openDrawer();
}
});
return fragmentLayout;
}
}
If you have any questions, let me know. Hoping it will be helped.
Upvotes: 1