‘setHasOptionsMenu(Boolean): Unidad’ está en desuso. En desuso en Java

6 minutos de lectura

¿Cómo declaro un menú dentro del fragmento de Android? El método que había usado anteriormente ahora está obsoleto.

Originalmente:

    override fun onCreateView(...): View {
        setHasOptionsMenu(true)
    }
 override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        super.onCreateOptionsMenu(menu, inflater)
        this.menu = menu
        inflater.inflate(R.menu.menu, this.menu)
    }

  • Leíste las notas de lanzamiento que se vinculó a la fragmentos de código?

    – ianhanniballake

    18 abr a las 23:01

  • ¡Gracias por el recurso! @ianhanniballake

    – SUR4IDE

    22 abr a las 14:19

  • ¿Por qué exactamente fue obsoleto? No veo nada especial en el nuevo código…

    – desarrollador de Android

    25 de mayo a las 1:04

De la documentación del desarrollador, esto se puede lograr de la siguiente manera:

/**
  * Using the addMenuProvider() API directly in your Activity
  **/
class ExampleActivity : ComponentActivity(R.layout.activity_example) {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Add menu items without overriding methods in the Activity
   addMenuProvider(object : MenuProvider {
      override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
        // Add menu items here
        menuInflater.inflate(R.menu.example_menu, menu)
      }

      override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
        // Handle the menu selection
        return true
      }
    })
  }
}

/**
  * Using the addMenuProvider() API in a Fragment
  **/
class ExampleFragment : Fragment(R.layout.fragment_example) {

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    // The usage of an interface lets you inject your own implementation
    val menuHost: MenuHost = requireActivity()
  
    // Add menu items without using the Fragment Menu APIs
    // Note how we can tie the MenuProvider to the viewLifecycleOwner
    // and an optional Lifecycle.State (here, RESUMED) to indicate when
    // the menu should be visible
    menuHost.addMenuProvider(object : MenuProvider {
      override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
        // Add menu items here
        menuInflater.inflate(R.menu.example_menu, menu)
      }

      override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
        // Handle the menu selection
            return when (menuItem.itemId) {
                R.id.menu_clear -> {
                    // clearCompletedTasks()
                    true
                }
                R.id.menu_refresh -> {
                    // loadTasks(true)
                    true
                }
                else -> false
            }
      }
    }, viewLifecycleOwner, Lifecycle.State.RESUMED)
  }

Fragmentos setHasOptionsMenu en desuso, use setHasOptionsMenu

  • ¿Qué pasa con otras funciones, como la invalidación y la obtención de una referencia a los elementos del menú? ¿Siguen existiendo o también han cambiado?

    – desarrollador de Android

    23 de mayo a las 6:13

  • en el fragmento necesitaría mantener la referencia al objeto MenuProvider para poder eliminarlo usando removeMenuProvider(MenuProvider obj) causa de menús duplicados en varios fragmentos… ¿sabe cómo hacerlo? Acabo de probarlo pero aún tengo el problema

    – ricardogabellona

    30 de junio a las 14:15


  • @riccardogabellone Tengo un problema similar, pero noté que puedes pasar el parámetro LifecycleOwner a la función addMenuProvider, lo que significa que en el fragmento uso esto: activity!!.addMenuProvider(menuProviderThatYouCreated, this.viewLifecycleOwner)

    – desarrollador de Android

    6 de julio a las 20:34


  • ¿Qué significa lo siguiente?: // El uso de una interfaz le permite inyectar su propia implementación

    – David

    6 de julio a las 23:53

  • val menuHost: MenuHost = requireActivity() en el fragmento veo que se requiere: MenuHost pero se encontró: FragmentActivity

    – Doctor Mido

    22 de julio a las 11:44

avatar de usuario de rogue
pícaro

Ampliando lo que dijeron @joseph-wambura y @hammad-zafar-bawara, también puede implementar la interfaz en el fragmento…

class MyFragment : Fragment(), MenuProvider {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        // Do stuff...
        val menuHost: MenuHost = requireActivity()
        menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED)
    }

    override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
        menuInflater.inflate(R.menu.options, menu)
        // Do stuff...
    }

    override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
        // Do stuff...
        return false
    }
}

  • val menuHost: MenuHost = requireActivity() en el fragmento veo que se requiere: MenuHost pero se encontró: FragmentActivity ¿Cómo puedo usarlo?

    – Doctor Mido

    22 de julio a las 11:45

  • Asegúrese de que está usando import androidx.fragment.app.Fragment y no el depreciado import android.app.Fragment

    – pícaro

    23 de julio a las 18:37

  • ya uso esto

    – Doctor Mido

    23 de julio a las 19:38

  • Este es un cambio forzado de ComponentActivity (y por extensión sus fragmentos). Hay desarrolladores que todavía usan CompatActivity sin el marco de componente forzado y las guías no explican cómo lograr esto para ese escenario. requireActivity() en ese caso arroja una falta de coincidencia de tipos.

    – Sombra

    26 de julio a las 19:17

  • La solución para esto es lanzarlo, así. val menuHost: MenuHost = requireActivity() as MenuHost

    – Sombra

    26 de julio a las 19:51

Avatar de usuario de Codelaby
códigolaby

En Kotlin, declaración para Activity, Fragment y PreferenceFragmentCompat

Actividad

class MainActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

   addMenuProvider(object : MenuProvider {
      override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
        menuInflater.inflate(R.menu.main_menu, menu)
      }

      override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
        // Handle the menu selection
        return true
      }
    })
  }
}

Fragmento

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

    // The usage of an interface lets you inject your own implementation
    val menuHost: MenuHost = requireActivity()

    menuHost.addMenuProvider(object : MenuProvider {
      override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
        // Add menu items here
        menuInflater.inflate(R.menu.main_menu, menu)
      }

      override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
        // Handle the menu selection
            return when (menuItem.itemId) {
                R.id.action_menu1 -> {
                    // todo menu1
                    true
                }
                R.id.action_menu2 -> {
                    // todo menu2
                    true
                }
                else -> false
            }
      }
    }, viewLifecycleOwner, Lifecycle.State.RESUMED)
 }

PreferenceFragmentCompatPreferenceFragmentCompat

val menuHost: MenuHost = requireHost() as MenuHost
//Same declaration with Fragment

Usar la interfaz de MenuProvider

class FirstFragment : Fragment(), MenuProvider {
 
      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
              val menuHost: MenuHost = requireActivity()
              menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED)
      }
 
      override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
        // Add menu items here
        menuInflater.inflate(R.menu.second_menu, menu)
      }
 
      override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
        // Handle the menu selection
            return when (menuItem.itemId) {
                R.id.menu_clear -> {
                    // Do stuff...
                    true
                }
                R.id.menu_refresh -> {
                    // Do stuff...
                    true
                }
                else -> false
            }
      }, viewLifecycleOwner, Lifecycle.State.RESUMED)
}

  • Basado en mi tweet y notas de blog personales, twitter.com/Codelaby/status/…

    – Codelaby

    14 de agosto a las 10:47

  • lo intenté pero val menuHost: MenuHost = requireActivity() dando error: Type mismatch: inferred type is FragmentActivity but MenuHost was expected

    – Josué

    13 de septiembre a las 4:40

  • Después de agregar implementation 'androidx.activity:activity-compose:1.5.1' el error desapareció gracias

    – Josué

    13 de septiembre a las 5:22

Avatar de usuario de Hammad Zafar Bawara
Hammad Zafar Bawara

CÓDIGO JAVA

Menú de opciones en Actividad

addMenuProvider(new MenuProvider() {
            @Override
            public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater menuInflater) {
                menuInflater.inflate(R.menu.bottom_nav_menu, menu);

                // Add menu options here

            }

            @Override
            public boolean onMenuItemSelected(@NonNull MenuItem menuItem) {

                // Handle Menu Options Selection Here

                return false;
            }
        });

Menú de opciones en Fragmento

requireActivity().addMenuProvider(new MenuProvider() {
            @Override
            public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater menuInflater) {
                menuInflater.inflate(R.menu.bottom_nav_menu, menu);
                
                // Add option Menu Here
                
            }

            @Override
            public boolean onMenuItemSelected(@NonNull MenuItem menuItem) {
                return false;
                
                // Handle option Menu Here
                
            }
        }, viewLifecycleOwner, Lifecycle.State.RESUMED);

esto me ayuda en el método onCreateView:

requireActivity().addMenuProvider(new MenuProvider() {
        @Override
        public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater menuInflater) {
            menuInflater.inflate(R.menu.bottom_nav_menu, menu);
            
            // Add option Menu Here
            
        }

        @Override
        public boolean onMenuItemSelected(@NonNull MenuItem menuItem) {
                           
            // Handle option Menu Here
             return false;
        }
    }, getViewLifecycleOwner, Lifecycle.State.RESUMED);

  • ¿Qué sucede si el proveedor de menús está en la actividad principal y solo quiero agregar un código cuando se hace clic en un elemento del menú cuando el fragmento está a la vista/enfocado? ¿También tengo que inflar en onCreateMenu?

    – Chitgoks

    2 de septiembre a las 3:02

Avatar de usuario de Eric B.
eric b

Si está utilizando Jetpack NavigationUI, debe setSupportActionBar(toolbar)de lo contrario el menú no estará presente.

  • ¿Qué sucede si el proveedor de menús está en la actividad principal y solo quiero agregar un código cuando se hace clic en un elemento del menú cuando el fragmento está a la vista/enfocado? ¿También tengo que inflar en onCreateMenu?

    – Chitgoks

    2 de septiembre a las 3:02

¿Ha sido útil esta solución?