菜单
用于显示下拉菜单的 SwiftUI Menu 组件。
Expo UI 菜单与官方 SwiftUI Menu API 匹配,并支持通过 buttonStyle 修饰符进行样式设置。菜单在单次点击时打开。对于长按交互,请改用 ContextMenu。
🌐 Expo UI Menu matches the official SwiftUI Menu API and supports styling via the buttonStyle modifier. Menu opens on a single tap. For long-press interactions, use ContextMenu instead.
注意: 在 tvOS 上,菜单需要 tvOS 17.0 或更高版本。
安装
🌐 Installation
- npx expo install @expo/uiIf you are installing this in an existing React Native app, make sure to install expo in your project.
用法
🌐 Usage
简单文本标签
🌐 Simple text label
import { Host, Menu, Button } from '@expo/ui/swift-ui'; export default function SimpleMenuExample() { return ( <Host matchContents> <Menu label="Options"> <Button label="Option 1" onPress={() => console.log('Option 1')} /> <Button label="Option 2" onPress={() => console.log('Option 2')} /> <Button label="Option 3" onPress={() => console.log('Option 3')} /> </Menu> </Host> ); }
带有 SF 符号的文本标签
🌐 Text label with SF Symbol
import { Host, Menu, Button, Divider } from '@expo/ui/swift-ui'; export default function MenuWithIconExample() { return ( <Host matchContents> <Menu label="More" systemImage="ellipsis.circle"> <Button label="Settings" systemImage="gear" onPress={() => console.log('Settings')} /> <Button label="Profile" systemImage="person" onPress={() => console.log('Profile')} /> <Divider /> <Button label="Delete" role="destructive" systemImage="trash" onPress={() => console.log('Delete')} /> </Menu> </Host> ); }
自定义标签
🌐 Custom label
你可以将 React 节点作为标签传递,以进行自定义样式。
🌐 You can pass a React node as the label for custom styling.
import { Host, Menu, Button, Text } from '@expo/ui/swift-ui'; export default function CustomLabelMenuExample() { return ( <Host matchContents> <Menu label={<Text color="accentColor">Custom Label</Text>}> <Button label="Action 1" onPress={() => console.log('Action 1')} /> <Button label="Action 2" onPress={() => console.log('Action 2')} /> </Menu> </Host> ); }
嵌套菜单
🌐 Nested menu
菜单可以嵌套以创建子菜单。
🌐 Menus can be nested to create submenus.
import { Host, Menu, Button } from '@expo/ui/swift-ui'; export default function NestedMenuExample() { return ( <Host matchContents> <Menu label="Main Menu"> <Button label="Item 1" onPress={() => console.log('Item 1')} /> <Menu label="Submenu"> <Button label="Sub Item 1" onPress={() => console.log('Sub Item 1')} /> <Button label="Sub Item 2" onPress={() => console.log('Sub Item 2')} /> </Menu> <Button label="Item 2" onPress={() => console.log('Item 2')} /> </Menu> </Host> ); }
使用主要动作
🌐 With primary action
当提供 onPrimaryAction 时,单击会触发主要操作,而长按会显示菜单。
🌐 When onPrimaryAction is provided, a single tap triggers the primary action while a long-press shows the menu.
import { Host, Menu, Button } from '@expo/ui/swift-ui'; export default function PrimaryActionMenuExample() { return ( <Host matchContents> <Menu label="Tap or Hold" systemImage="play.circle" onPrimaryAction={() => console.log('Primary action triggered!')}> <Button label="Menu Item 1" onPress={() => console.log('Menu Item 1')} /> <Button label="Menu Item 2" onPress={() => console.log('Menu Item 2')} /> <Button label="Menu Item 3" onPress={() => console.log('Menu Item 3')} /> </Menu> </Host> ); }
使用修饰符进行样式化
🌐 Styling with modifiers
你可以使用 buttonStyle 修饰符来更改菜单触发器的外观。
🌐 You can use the buttonStyle modifier to change the appearance of the menu trigger.
import { Host, Menu, Button } from '@expo/ui/swift-ui'; import { buttonStyle } from '@expo/ui/swift-ui/modifiers'; export default function StyledMenuExample() { return ( <Host matchContents> <Menu label="Styled Menu" modifiers={[buttonStyle('borderedProminent')]}> <Button label="Styled Action 1" onPress={() => console.log('Styled 1')} /> <Button label="Styled Action 2" onPress={() => console.log('Styled 2')} /> </Menu> </Host> ); }
有对照组
🌐 With control group
在菜单中使用ControlGroup来渲染一行水平的图标按钮,类似于 Apple Music 或 Safari 菜单中的快速操作行。
🌐 Use a ControlGroup inside a menu to render a horizontal row of icon buttons, similar to the quick actions row in Apple Music or Safari menus.
import { Host, Menu, ControlGroup, Button, Section, Divider } from '@expo/ui/swift-ui'; export default function MenuWithControlGroupExample() { return ( <Host matchContents> <Menu label="Song Options" systemImage="ellipsis.circle"> <ControlGroup> <Button systemImage="plus" label="Add" onPress={() => console.log('Add')} /> <Button systemImage="star" label="Favorite" onPress={() => console.log('Favorite')} /> <Button systemImage="square.and.arrow.up" label="Share" onPress={() => console.log('Share')} /> </ControlGroup> <Section> <Button systemImage="text.badge.plus" label="Add to a Playlist" onPress={() => console.log('Add to Playlist')} /> <Button systemImage="antenna.radiowaves.left.and.right" label="Create Station" onPress={() => console.log('Create Station')} /> </Section> <Divider /> <Button systemImage="hand.thumbsdown" label="Suggest Less" onPress={() => console.log('Suggest Less')} /> </Menu> </Host> ); }
仅图标菜单按钮
🌐 Icon only menu button
使用 labelStyle('iconOnly') 修饰符仅显示图标而不显示标签文字。为了无障碍访问,仍应提供 label 属性。
🌐 Use the labelStyle('iconOnly') modifier to display only the icon without the label text. The label prop should still be provided for accessibility purposes.
import { Host, Menu, Button } from '@expo/ui/swift-ui'; import { labelStyle } from '@expo/ui/swift-ui/modifiers'; export default function IconOnlyMenuExample() { return ( <Host matchContents> <Menu label="Icon Only Button" systemImage="gear" modifiers={[labelStyle('iconOnly')]}> <Button label="Menu Item 1" onPress={() => console.log('Menu Item 1')} /> <Button label="Menu Item 2" onPress={() => console.log('Menu Item 2')} /> <Button label="Menu Item 3" onPress={() => console.log('Menu Item 3')} /> </Menu> </Host> ); }
应用接口
🌐 API
import { Menu } from '@expo/ui/swift-ui';
Component
Type: React.Element<MenuProps>
Displays a dropdown menu when tapped.
Props for the Menu component.
ReactNodeThe menu's content items, which are shown when the menu is opened.
Can contain Button, Toggle, Picker, Section, Divider or nested Menu components.
unionThe label for the menu trigger. Can be a string for simple text labels, or a ReactNode for custom label content.
Acceptable values are: string | ReactNode
() => voidA callback that is invoked when the user taps the menu label. When provided, a single tap triggers this action, while a long-press shows the menu. When not provided, a single tap shows the menu.
stringAn SF Symbol name to display alongside the label.
Only used when label is a string.