0

According to this question, I tried to update my deprecated menus codes like setHasOptionsMenu , onCreateOptionsMenu and onOptionsItemSelected in my fragments and all app, but I should replace AppCompatActivity to ComponentActivity(R.layout.activity_example) but after doing this I see there's some problem, first I confused about how to use ViewBinding with it when I should remove setContentView(binding.root) from activity second the method setSupportActionBar(binding.appBarMain.toolbar) is not found, and I couldn't use the navigation components like supportFragmentManager and setupActionBarWithNavController the third thing I couldn't"t declare this
val menuHost: MenuHost = requireActivity() in onCreateView in fragment I see it's Required: MenuHost but Found: FragmentActivity

enter image description here

menu updates

here's my MainActivity code before edits

@AndroidEntryPoint class MainActivity : AppCompatActivity() { private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var binding: ActivityMainBinding private lateinit var navController: NavController private lateinit var postViewModel: PostViewModel private lateinit var navGraph: NavGraph override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) postViewModel = ViewModelProvider(this)[PostViewModel::class.java] postViewModel.getCurrentDestination() setSupportActionBar(binding.appBarMain.toolbar) val drawerLayout: DrawerLayout = binding.drawerLayout val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment? if (navHostFragment != null) { navController = navHostFragment.navController } navGraph = navController.navInflater.inflate(R.navigation.mobile_navigation) // Passing each menu ID as a set of Ids because each // menu should be considered as top level destinations. appBarConfiguration = AppBarConfiguration( setOf( R.id.nav_home, R.id.nav_accessory, R.id.nav_arcade, R.id.nav_fashion, R.id.nav_food, R.id.nav_heath, R.id.nav_lifestyle, R.id.nav_sports, R.id.nav_favorites, R.id.about ), drawerLayout ) // setupActionBarWithNavController(navController, appBarConfiguration) // navView.setupWithNavController(navController) setupActionBarWithNavController(this, navController, appBarConfiguration) setupWithNavController(binding.navView, navController) // determineAdvertisingInfo() } override fun onSupportNavigateUp(): Boolean { return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() } } 

and this the implementation of menus in fragments

 override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentHomeBinding.inflate(inflater, container, false) setHasOptionsMenu(true) return binding.root } .................................................................................... override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.main, menu) super.onCreateOptionsMenu(menu, inflater) val searchManager = requireContext().getSystemService(Context.SEARCH_SERVICE) as SearchManager val searchView = menu.findItem(R.id.app_bar_search).actionView as SearchView searchView.setSearchableInfo(searchManager.getSearchableInfo(requireActivity().componentName)) searchView.queryHint = resources.getString(R.string.searchForPosts) searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(keyword: String): Boolean { if (keyword.isEmpty()) { Snackbar.make( requireView(), "please enter keyword to search", Snackbar.LENGTH_SHORT ).show() } // itemArrayList.clear() if (Utils.hasInternetConnection(requireContext())) { postViewModel.getItemsBySearch(keyword) postViewModel.searchedPostsResponse.observe(viewLifecycleOwner) { response -> when (response) { is NetworkResult.Success -> { hideShimmerEffect() itemArrayList.clear() binding.progressBar.visibility = View.GONE response.data?.let { itemArrayList.addAll(it.items) } adapter.notifyDataSetChanged() } is NetworkResult.Error -> { hideShimmerEffect() // loadDataFromCache() Toast.makeText( requireContext(), response.toString(), Toast.LENGTH_LONG ).show() } is NetworkResult.Loading -> { if (postViewModel.recyclerViewLayout.value == "titleLayout" || postViewModel.recyclerViewLayout.value == "gridLayout" ) { hideShimmerEffect() } else { showShimmerEffect() } } } } } else { postViewModel.getItemsBySearchInDB(keyword) postViewModel.postsBySearchInDB.observe(viewLifecycleOwner) { items -> if (items.isNotEmpty()) { hideShimmerEffect() binding.progressBar.visibility = View.GONE itemArrayList.clear() itemArrayList.addAll(items) adapter.notifyDataSetChanged() } } } return false } override fun onQueryTextChange(newText: String): Boolean { return false } }) searchView.setOnCloseListener { if (Utils.hasInternetConnection(requireContext())) { Log.d(TAG, "setOnCloseListener: called") itemArrayList.clear() requestApiData() } else { noInternetConnectionLayout() } false } postViewModel.searchError.observe(viewLifecycleOwner) { searchError -> if (searchError) { Toast.makeText( requireContext(), "There's no posts with this keyword", Toast.LENGTH_LONG ).show() } } } override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == R.id.change_layout) { changeAndSaveLayout() return true } return super.onOptionsItemSelected(item) } 

build.gradle dependencies

dependencies { implementation 'androidx.core:core-ktx:1.6.0' implementation 'androidx.appcompat:appcompat:1.4.2' implementation ('com.google.android.material:material:1.6.1') { exclude(group: 'androidx.recyclerview', module: 'recyclerview') exclude(group: 'androidx.recyclerview', module: 'recyclerview-selection') } implementation "androidx.recyclerview:recyclerview:1.2.1" // For control over item selection of both touch and mouse driven selection implementation "androidx.recyclerview:recyclerview-selection:1.1.0" implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.0' implementation 'androidx.navigation:navigation-fragment-ktx:2.5.0' implementation 'androidx.navigation:navigation-ui-ktx:2.5.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' //Retrofit implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // //Moshi // implementation("com.squareup.moshi:moshi:1.13.0") // implementation("com.squareup.retrofit2:converter-moshi:2.9.0") // kapt "com.squareup.moshi:moshi-kotlin-codegen:1.13.0" implementation 'com.github.bumptech.glide:glide:4.12.0' implementation 'org.jsoup:jsoup:1.14.1' implementation 'com.squareup.picasso:picasso:2.71828' implementation 'org.apache.commons:commons-lang3:3.8.1' implementation 'org.ocpsoft.prettytime:prettytime:4.0.1.Final' implementation "androidx.browser:browser:1.4.0" implementation 'androidx.multidex:multidex:2.0.1' configurations { all*.exclude group: 'com.google.guava', module: 'listenablefuture' } //Room implementation "androidx.room:room-runtime:2.4.2" kapt "androidx.room:room-compiler:2.4.2" implementation "androidx.room:room-ktx:2.4.2" androidTestImplementation "androidx.room:room-testing:2.4.2" //Dagger - Hilt implementation 'com.google.dagger:hilt-android:2.42' kapt 'com.google.dagger:hilt-android-compiler:2.42' //SDP & SSP implementation 'com.intuit.sdp:sdp-android:1.0.6' implementation 'com.intuit.ssp:ssp-android:1.0.6' // Shimmer implementation 'com.facebook.shimmer:shimmer:0.5.0' //firebase & analytics implementation platform('com.google.firebase:firebase-bom:28.4.0') implementation 'com.google.firebase:firebase-analytics' //crashlytics implementation 'com.google.firebase:firebase-crashlytics' implementation 'com.google.firebase:firebase-analytics' // DataStore implementation 'androidx.datastore:datastore-preferences:1.0.0' implementation("androidx.datastore:datastore-preferences-rxjava3:1.0.0") //admob implementation 'com.google.android.gms:play-services-ads:21.1.0' implementation platform('com.google.firebase:firebase-bom:30.2.0') implementation project(':nativetemplates') implementation("androidx.ads:ads-identifier:1.0.0-alpha04") // Used for the calls to addCallback() in the snippets on this page. implementation("com.google.guava:guava:28.0-android") implementation 'com.google.firebase:firebase-analytics' implementation("androidx.activity:activity-ktx:1.5.0") } 
7
  • 3
    AppCompatActivity extends ComponentActivity, so just keep using AppCompatActivity. Commented Jul 22, 2022 at 2:48
  • 1
    And putting the layout in the superconstructor call is just an alternative to using setContentView(). If you choose to use the superconstructor way of doing it, you need to use your binding's bind() function instead of its inflate() function to bind to the already-inflated view. If you're using view binding, it's probably simpler to do it using inflate instead of passing the layout to the superconstructor. Commented Jul 22, 2022 at 3:21
  • @ianhanniballake If I keep using AppCompatActivity then How can I use the new menus implementation in fragment? val menuHost: MenuHost = requireActivity() it is related with extended of ComponentActivity ? Commented Jul 22, 2022 at 11:34
  • 1
    You'd have to be using a very, very, very old version of AppCompat and Fragment to not have FragmentActivity and AppCompatActivity extend ComponentActivity. Please include the dependencies block from your build.gradle file if you'd like us to look at what versions you are using. Commented Jul 22, 2022 at 16:58
  • 1
    Yep, your FragmentActivity definitely extends ComponentActivity and therefore has access to the MenuHost interface that ComponentActivity implements. Commented Jul 22, 2022 at 22:21

1 Answer 1

3
+50

Simplest solution from top of my head (hopefully it will work for you):

val menuHost: MenuHost = requireActivity() as MenuHost 

This example is for fragment but I guess you can easily apply it to activity:

First extend fragment with MenuProvider:

class SomeFragment : SomethingIfYouHave(), MenuProvider { /* Your code */ } 

Now in onCreateView:

val menuHost: MenuHost = requireActivity() as MenuHost menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED) 

Later in code override onCreateMenu and onMenuItemSelected.

override fun onCreateMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.info_menu, menu) } override fun onMenuItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.something-> { // Do something here true } else -> false } } 

AppCompatActivity extends FragmentActivity which extends ComponentActivity, why to use ComponentActivity directly?

Please revert it to:

class MainActivity : AppCompatActivity() { /* Your code here */ } 

I think your only problem was in this line:

val menuHost: MenuHost = requireActivity() as MenuHost 

------------------- UPDATE

*ComponentActivity has all you need for a Compose-only app. If you need AppCompat APIs, an AndroidView which works with AppCompat or MaterialComponents theme, or you need Fragments then use AppCompatActivity.

You are not using purely ComposeUI, so that is why you need AppCompat and not ComponentActivity.

If you want to use ComponentActivity without AppCompat you need to get rid off supportFragmentManager.

This would go out of the scope but please check ComposeUI Fragments if you want to switch on ComposeUI (I didn't write article).

Sign up to request clarification or add additional context in comments.

5 Comments

@gaming-ingrs thank you, so the trick for this problem was in casting as MenuHost simple like that :D , so to complete the answer to this question Can you edit your answer and add how to use the ComponentActivity(R.layout.activity_example) in activity with viewBinding and setSupportActionBar and supportFragmentManager because I used this in my app
I am not sure why do you want to use ComponentActivity directly as AppCompatActivity extends FragmentActivity which extends ComponentActivity? You should revert it to AppCompatActivity and if you have any error after that please let me know.
Updated my answer based on my comment above so please check it out.
@gaming-ingrs I am not sure if you understand my previous reply, but you can check this answer to relate He used class ExampleActivity : ComponentActivity(R.layout.activity_example) in activity so I thought to use new menus API "Using the addMenuProvider() API directly in your Activity" it should extend ComponentActivity not AppCompatActivity
Please check my update.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.