ios - 如何在 UIMenu 显示支持动态操作之前对其进行修改
问题描述
iOS 14 添加了在点击或长按 UIBarButtonItem 或 UIButton 时显示菜单的功能,如下所示:
let menu = UIMenu(children: [UIAction(title: "Action", image: nil) { action in
//do something
}])
button.menu = menu
barButtonItem = UIBarButtonItem(title: "Show Menu", image: nil, primaryAction: nil, menu: menu)
这通常会替换操作表(UIAlertController
带有actionSheet
样式)。拥有一个动态操作表非常常见,其中仅包含操作,或者根据用户点击按钮时的某些状态可能会禁用操作。但是使用此 API,菜单是在创建按钮时创建的。您如何在菜单出现之前对其进行修改或以其他方式使其动态化以确保适当的操作可用并在出现时处于适当的状态?
解决方案
您可以存储对条形按钮项或按钮的引用,并在每次影响菜单中可用操作的任何状态更改时重新创建菜单。menu
是一个可设置的属性,因此可以在创建按钮后随时更改。您还可以像这样获取当前菜单并替换其子项:button.menu = button.menu?.replacingChildren([])
例如,对于在状态更改时未通知您的情况,您确实需要能够在菜单出现之前对其进行更新。有一个UIDeferredMenuElement
API 允许动态生成操作。这是一个块,您可以在其中调用提供数组的完成处理程序UIMenuElement
。带有加载 UI 的占位符由系统添加,并在您调用完成处理程序后被替换,因此它支持异步确定菜单项。然而,这个块只被调用一次,然后它被缓存和重用,所以这并不能满足我们在这个场景中所需要的。iOS 15 添加了一个新的未缓存提供程序 API,其行为方式相同,只是每次显示元素时都会调用块,这正是我们在这种情况下所需要的。
barButtonItem.menu = UIMenu(children: [
UIDeferredMenuElement.uncached { [weak self] completion in
var actions = [UIMenuElement]()
if self?.includeTestAction == true {
actions.append(UIAction(title: "Test Action") { [weak self] action in
self?.performTestAction()
})
}
completion(actions)
}
])
在此 API 存在之前,我确实为UIButton
您发现可以在用户通过目标/操作按下时更改菜单,如下所示button.addTarget(self, action: #selector(buttonTouchedDown(_:)), for: .touchDown)
:这只有showsMenuAsPrimaryAction
在错误的情况下才有效,因此他们必须长按才能打开菜单。我没有找到解决方案UIBarButtonItem
,但您可以使用 aUIButton
作为自定义视图。
推荐阅读
- html - 如何使 div 在 HTML 中到达页面底部
- python-3.x - 在字节数组的末尾是否需要显式 NUL 字节,以便 cython 能够将其转换为以 null 结尾的 C 字符串
- jquery - 使用 jQuery 获取具有类的最近的前一个元素
- android - 如何在viewpager中单击按钮上的滑动保存图像
- file - 如何在不丢失公共访问权限的情况下更改文件夹名称
- html - 假设放置了未正确放置的按钮。CSS。HTML
- javascript - Vue.js 键盘事件不起作用
- php - PHP MS SQL - 致命错误:调用未定义函数 sqlsvr_connect()
- qt - 使用 ICC 构建 Qt 失败
- node.js - 当 firebase-admin 写入数据时,使用规则验证 Firebase