VisionPro开发 - Tab Bar & Side Bar


首页:漫游Apple Vision Pro

Code Repo: Github - VisionOS Workshop


基本概念

苹果的各个OS生态中,有各种不同的导航栏、工具栏组件。不同组件适用的平台也不完全相同。

根据官方文档总结如下:

DefinitioniOSiPadOSMacOStvOSvisionOSwatchOS
Tab barTab bar docTab bars use bar items to navigate between mutually exclusive panes of content in the same view.×Highly customizable×
Tab viewTab view docA tab view presents multiple mutually exclusive panes of content in the same area, which people can switch between using a tabbed control.××××
Side barSide bar docA sidebar can help people navigate your app or game, providing quick access to top-level collections of content.Consider using a tab bar instead of a sidebarNo additional considerations for tvOS×
Tool barTool bar docA toolbar provides convenient access to frequently used commands and controls that perform actions relevant to the current view.Offers commonly used actionsHighly customizable
OrnamentsOrnaments docAn ornament presents controls and information related to a window, without crowding or obscuring the window’s contents.×××××

这里我们先讨论Tab bar和Side bar两种形式。

Tab bar

Tab bar会在同一区域呈现多个互斥的内容面板,用户可以通过标签控件进行切换。手机屏幕较高,因此在iOS中,b bar在屏幕底部。而在visionOS中,由于不受屏幕尺寸的限制,所以通过悬浮于窗口外的侧边栏实现。

image.png

Side bar

Side bar则更适用于宽屏幕设备,如macOS,iPadOS以及visionOS。

image.png

因此对于visionOS而言,可以同时有Tab bar和Side bar两层结构进行导航操作。

实现

Tab bar

Tab bar提供多个View的切换。实现中顶层是一个TabView<SelectionValue, Content>。其中SelectionValue表示当前选中的View,Content表示它包含的子页面。

对于每个子页面,需要通过.tag.tabItem两个modifier提供更具体的信息

  • .tag为每个View提供唯一的tag
  • .tabItem提供图标和文案。默认展示图标,用户注视时图标会展开,显示详细的文案

这样,我们就可以获得一个Tab bar。

TabView(selection: $barIdx,
        content:  {
    Text("Tab Content 1")
        .tabItem {
            Label("Albums", systemImage: "rectangle.stack.fill")
        }
        .tag(1)
    Text("Tab Content 2")
        .tabItem {
            Label("Memories", systemImage: "memories")
        }
        .tag(2)
    // ...
})

数据可以通过@Environment以注入的方式传递,并且为每个选项渲染对应的页面。

struct ContentView: View {
    
    @State var barIdx = 1
    @Environment(ViewModel.self) var viewModel;
    
    var body: some View {
        
        @Bindable var viewModel = viewModel
        
        TabView(selection: $barIdx, content: {
            ForEach(viewModel.models) { model in
                PageView(dataModel : model)
                    .tabItem { Label(model.labelName, systemImage: model.labelImage) }
                    .tag(model.id)
            }
        })
    }
}

Side bar

Side bar顶层是NavigationSplitView,它包含2-3列,其中第一列控制后几列的展示。每一个选项页面是一个NavigationLink

NavigationSplitView() {
    List {
        NavigationLink {
            Text(dataModel.description)
            Text("Recent view")
        } label: {
            Label("Recent", systemImage: "clock")
        }
        NavigationLink {
            Text(dataModel.description)
            Text("Favorite view")
        } label: {
            Label("Favorite", systemImage: "suit.heart")
        }
    }
    .navigationTitle(dataModel.labelName)
} detail: {
    Text("Select an item")
}

这样我们就可以获得一个拥有2层级导航的页面。

最终效果

TabBarAndSideBar

欢迎关注公众号请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值