当尝试像往常一样在 onCreate 和
setHasOptionsMenu(true)
中写入 override fun onCreateOptionsMenu
时,Android Studio 会划掉这些函数,表示它们已被弃用。
我看了他们的建议
https://developer.android.com/jetpack/androidx/releases/activity?authuser=5#1.4.0-alpha01
事实证明,他们要求在 Activity (MainActivity.kt) 中插入一些新函数,在 Fragment (DogListFragment.kt) 中插入一些新函数。但在我的应用程序中,所有菜单自定义仅在 Fragment 中完成,因此 Activity 无法做到这一点。 Activity 根本无法访问 RecyclerView,它位于属于 Fragment 的布局 (fragment_god_list.xml) 中。 Activity 的 Activity_main.xml 中只有
androidx.fragment.app.FragmentContainerView
有谁知道如何在 Fragment 中完成此操作,而无需对 Activity 中的菜单进行任何操作?
GitHub 项目: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>
当您调用 setUpActionBarWithNavController() 方法时,您正在活动内设置工具栏。您的片段位于此活动内。你的片段也有这个actionBar。要在片段内使用菜单提供程序,您需要在片段的 onViewCreated() 方法内调用以下方法。
requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED)
此外,您需要使您的片段实现 MenuProvider 接口
class DogListFragment : Fragment(),MenuProvider {...
IDE 会要求您实现其提供者方法,即 onCreateMenu 和 onMenuItemSelected 在 OnCreateMenu 内部,使用 menu Inflator 来膨胀菜单布局 示例:-
menuInflater.inflate(R.menu.search_menu,menu)
没有人为我工作过。 只有以下过程有效。我认为这个原因是我从 xml 文件实现了菜单
在xml中添加了这部分
来自 CreatedView 上的片段
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
)