2

When trying to write setHasOptionsMenu(true) in onCreate and override fun onCreateOptionsMenu as usual, Android Studio crosses out these functions saying that they are deprecated.

I looked at what they suggest

https://developer.android.com/jetpack/androidx/releases/activity?authuser=5#1.4.0-alpha01

and it turns out that they are asking to insert some new functions in Activity (MainActivity.kt) and some in Fragment (DogListFragment.kt). But in my app, all menu customization was done only in Fragment, so Activity can't do that. Activity simply doesn't have access to the RecyclerView, which is in the layout (fragment_god_list.xml) that belongs to Fragment. Activity only has androidx.fragment.app.FragmentContainerView in its activity_main.xml

Does anyone know how this can be done in Fragment without having to do anything with the menus in Activity?

GitHub project: https://github.com/theMagusDev/DogglersApp

MainActivity.kt:

package com.example.dogglers import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.setupActionBarWithNavController import com.example.dogglers.databinding.ActivityMainBinding private lateinit var navController: NavController class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Setup view binding val binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // Setup navController val navHostFragment = supportFragmentManager .findFragmentById(R.id.nav_host_fragment) as NavHostFragment navController = navHostFragment.navController setupActionBarWithNavController(navController) } override fun onSupportNavigateUp(): Boolean { return navController.navigateUp() || super.onSupportNavigateUp() } } 

DogListFragment.kt:

package com.example.dogglers import android.os.Bundle import android.view.* import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.example.dogglers.adapter.DogCardAdapter import com.example.dogglers.const.Layout import com.example.dogglers.databinding.FragmentDogListBinding class DogListFragment : Fragment() { private var _binding: FragmentDogListBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! private lateinit var recyclerView: RecyclerView private var layoutType = Layout.VERTICAL override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { _binding = FragmentDogListBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { recyclerView = binding.verticalRecyclerView setUpAdapter() } override fun onDestroyView() { super.onDestroyView() _binding = null } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.layout_manu, menu) val layoutButton = menu.findItem(R.id.action_switch_layout) // Calls code to set the icon setIcon(layoutButton) } override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.action_switch_layout -> { layoutType = when (layoutType) { Layout.VERTICAL -> Layout.HORIZONTAL Layout.HORIZONTAL -> Layout.GRID else -> Layout.VERTICAL } setUpAdapter() return true } // Otherwise, do nothing and use the core event handling // when clauses require that all possible paths be accounted for explicitly, // for instance both the true and false cases if the value is a Boolean, // or an else to catch all unhandled cases. else -> return super.onOptionsItemSelected(item) } } fun setUpAdapter() { recyclerView.adapter = when(layoutType){ Layout.VERTICAL -> { recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false) DogCardAdapter( context, Layout.VERTICAL ) } Layout.HORIZONTAL -> { recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false) DogCardAdapter( context, Layout.HORIZONTAL ) } else -> { recyclerView.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false) DogCardAdapter( context, Layout.GRID ) } } } private fun setIcon(menuItem: MenuItem?) { if (menuItem == null) return menuItem.icon = when(layoutType) { Layout.VERTICAL -> ContextCompat.getDrawable(this.requireContext(), R.drawable.ic_vertical_layout) Layout.HORIZONTAL -> ContextCompat.getDrawable(this.requireContext(), R.drawable.ic_horizontal_layout) else -> ContextCompat.getDrawable(this.requireContext(), R.drawable.ic_grid_layout) } } } 

ActivityMain.xml:

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.fragment.app.FragmentContainerView 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:navGraph="@navigation/nav_graph"/> </FrameLayout> 

FragmentDogList:

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/vertical_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical" android:orientation="vertical" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" tools:listitem="@layout/vertical_list_item"/> </FrameLayout> 
5
  • The examples were just showing how the exact same API applies to activity based menus and fragment based menus - you don't implement them both. Commented Oct 2, 2022 at 15:35
  • This is already answered here : stackoverflow.com/a/73080607/14778218 Commented Oct 2, 2022 at 15:37
  • Thank you so much, @ianhanniballake, it all worked out! I thought I had to change the code in both files, but it turned out to be much easier. Commented Oct 2, 2022 at 16:02
  • 1
    Does this answer your question? 'setHasOptionsMenu(Boolean): Unit' is deprecated. Deprecated in Java Commented Oct 3, 2022 at 1:55
  • Yes, this question contains the same code from the android website. I just didn't know that it doesn't need to be embedded in both Activity and Fragment, it's enough to do it in the fragment. And I easily changed the code to fit my menu, I had no problem with that. Commented Oct 3, 2022 at 15:41

2 Answers 2

1

When you call setUpActionBarWithNavController() method , you are setting up toolbar inside the activity. Your Fragment is inside this activity. Your fragment has this actionBar too. To use Menu provider inside fragment, you need to call below method inside of onViewCreated() method of fragment.

requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED) 

Also, You need to make your fragment implement MenuProvider Interface

class DogListFragment : Fragment(),MenuProvider {... 

IDE will ask you to implement its provider method i.e onCreateMenu and onMenuItemSelected Inside OnCreateMenu, use menu Inflator to inflate menu layout example:-

 menuInflater.inflate(R.menu.search_menu,menu) 
Sign up to request clarification or add additional context in comments.

Comments

0

No one have been worked to me. Only bellow process worked. I think this cause is I implemented menu from xml file

  1. Added this part in xml

    <com.google.android.material.appbar.MaterialToolbar android:id="@+id/materialToolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/toolbar" app:layout_constraintTop_toTopOf="parent" app:title="Video on frame" app:menu="@menu/menu_home_frame" app:navigationIcon="@drawable/ic_menu" app:titleTextColor="@color/white" />

  2. from Fragment onCreatedView

     binding.materialToolbar.addMenuProvider( object : MenuProvider{ override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { ///No need to implement. Al } override fun onMenuItemSelected(menuItem: MenuItem): Boolean { return when (menuItem.itemId) { R.id.btn_booster -> { startBoosterActivity() true } R.id.btn_premium -> { startActivity(PremiumActivity::class.java) true } R.id.btn_search -> { startActivity(SearchActivity::class.java) true } else -> false } } }, viewLifecycleOwner, Lifecycle.State.RESUMED ) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.