'setHasOptionsMenu(Boolean): Unit'已弃用。在 Java 中已弃用



如何在Android fragment中声明一个菜单?我以前使用的方法现在不推荐了。

最初:

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)
}

从Developer文档中,可以通过以下方式实现:

/**
* 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)
}

Fragments setHasOptionsMenu已弃用,使用setHasOptionsMenu

扩展@joseph-wambura和@hammad-zafar-bawara所说的,您还可以在片段中实现接口…

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
}
}

Kotlin中Activity,FragmentPreferenceFragmentCompat的声明

活动
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
}
})
}
}

片段
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)
}

PreferenceFragmentCompat

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

使用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)
}

JAVA CODE

活动中的选项菜单

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;
}
});

Fragment中的选项菜单

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);

如果你正在使用Jetpack NavigationUI,那么你需要setSupportActionBar(toolbar),否则菜单将不存在

这有助于我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);

我不确定为什么所有答案都建议将Lifecycle.State.RESUME作为生命周期状态传递给addMenuProvider调用。这将使菜单在片段暂停时消失,当片段暂停但仍然可见时,这看起来不太好。

例如,点击菜单项显示对话框将使菜单消失。当对话框被取消时,它会重新出现。

对于大多数情况,传递一个更好的生命周期状态是Lifecycle.State.CREATE,它只会在视图被销毁时删除菜单。这也是默认行为,因此您可以简单地忽略生命周期状态。

对于那些有Java闪回的人来说,这里有一个更好的方法使用这个扩展函数:

fun Fragment.addMenuProvider(@MenuRes menuRes: Int, callback: (id: Int) -> Boolean) {
val menuProvider = object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(menuRes, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem) = callback(menuItem.itemId)
}
(requireActivity() as MenuHost).addMenuProvider(
menuProvider,
viewLifecycleOwner,
Lifecycle.State.RESUMED
)
}

和用法:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
addMenuProvider(R.menu.feed_fragment) {
when (it) {
R.id.menu_write_post -> viewModel.goToPostCreation()
R.id.menu_filter -> viewModel.goToFilter()
else -> false
}
}
}

如果需要功能标志,则可以多次重复addMenuProvider调用

在Java片段我试过这个。这对我来说很好

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_example, container, false);
toolbar = (Toolbar)view.findViewById(R.id.toolbar_1);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
MenuHost menuHost = requireActivity();
menuHost.addMenuProvider(new MenuProvider() {
@Override
public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater menuInflater) {
menuInflater.inflate(R.menu.menu_search,menu);
}
@Override
public boolean onMenuItemSelected(@NonNull MenuItem menuItem) {
if (menuItem.getItemId() == R.id.search_friend){
Toast.makeText(getActivity(), "friends", Toast.LENGTH_SHORT).show();
return true;
}
else return false;
}
},getViewLifecycleOwner(), Lifecycle.State.RESUMED);

return view;
}

除了上面的答案,我更喜欢创建一个扩展函数来减少样板代码:

扩展函数实现:

fun Fragment.setupMenu(@MenuRes menuId: Int, onMenuSelected: (MenuItem) -> Boolean) =
(requireActivity() as MenuHost).addMenuProvider(object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) =
menuInflater.inflate(menuId, menu)
override fun onMenuItemSelected(menuItem: MenuItem) = onMenuSelected(menuItem)
}, viewLifecycleOwner, Lifecycle.State.RESUMED)

这样,您将始终确保添加了lifeCycleOwner并传递了正确的lifecycle state,即Lifecycle.State.RESUMED

你可以简单地使用这个内部片段调用:

setupMenu(R.menu.menu_save) { menuItem ->
when (menuItem.itemId) {
R.id.save -> {
viewModel.onSaveClicked()
true
}
else -> false
}
}

最新更新