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>