avatar

Charlie的博客

学习进步 学习进步 学习进步

  • 首页
  • 后端
  • 前端
  • 移动端
  • 操作系统
Home 打造可滑动切换的顶部TabBar
文章

打造可滑动切换的顶部TabBar

Posted 2024-05-8 Updated 2024-11- 18
By Administrator
10~13 min read

SwiftUI技能UPUP:打造可滑动切换的顶部TabBar

在SwiftUI应用中,实现一个带有可滑动切换的顶部TabBar是一个常见的需求。本文将介绍如何使用SwiftUI创建一个具有这种功能的界面。

B站视频教程

准备工作

首先,我们需要定义一个 ContentView 结构体,其中包含了一些必要的状态变量和数据。具体代码如下:

struct ContentView: View {
    @State private var selectedTabIndex = 0
    @State private var selectedTabID: Int? = nil
    
    let tabTitles = ["Tab 1", "Tab 2", "Tab 3", "Tab 4", "Tab 5", "Tab 6", "Tab 7", "Tab 8", "Tab 9", "Tab 10"]
    
    var body: some View {
        // 界面布局代码在这里
    }
}

创建界面布局

我们使用 GeometryReader 来获取屏幕的尺寸,并在垂直方向上创建一个 VStack,在其中包含一个水平滚动的 ScrollView 和一个 TabView,分别用于显示选项卡和选项卡内容。

GeometryReader(content: { geometry in
    VStack (spacing: 0) {
        ScrollView(.horizontal, showsIndicators: false) {
            LazyHStack(spacing: 20) {
                ForEach(0..<tabTitles.count, id: \.self) { index in
                    // 每个选项卡按钮的代码
                }
            }
        }
        .scrollPosition(id: $selectedTabID, anchor: .center)
        .frame(height: 50)
    
        // Content views for each tab
        TabView(selection: $selectedTabIndex) {
            ForEach(0..<tabTitles.count, id: \.self) { index in
                // 每个选项卡内容的代码
            }
        }
        .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
        .indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .never))
    }
})

实现交互功能

最后,我们使用 Button 和 onChange 等函数来实现选项卡之间的切换功能,并添加一些动画效果,提升用户体验。

.onChange(of: selectedTabIndex) { oldValue, newValue in
    withAnimation {
        selectedTabIndex = newValue
        selectedTabID = newValue
    }
}

完整源码

import SwiftUI

struct ContentView: View {
    @State private var selectedTabIndex = 0
    @State private var selectedTabID: Int? = nil
    
    let tabTitles = ["Tab 1", "Tab 2", "Tab 3", "Tab 4", "Tab 5", "Tab 6", "Tab 7", "Tab 8", "Tab 9", "Tab 10"]
    
    var body: some View {
        GeometryReader(content: { geometry in
            VStack (spacing: 0) {
                ScrollView(.horizontal, showsIndicators: false) {
                    LazyHStack(spacing: 20) {
                        ForEach(0..<tabTitles.count, id: \.self) { index in
                            Button(action: {
                                withAnimation {
                                    selectedTabIndex = index
                                    selectedTabID = index
                                }
                            }) {
                                Text(tabTitles[index])
                                    .font(.headline)
                                    .foregroundColor(selectedTabIndex == index ? .red : .black)
                                    .frame(width: 60)
                            }
                        }
                    }
                    
                }
                .scrollPosition(id: $selectedTabID, anchor: .center)
                .frame(height: 50)
            
                // Content views for each tab
                TabView(selection: $selectedTabIndex) {
                    ForEach(0..<tabTitles.count, id: \.self) { index in
                        ZStack {
                            Color(uiColor: .systemGray6)
                            Text("Content for \(tabTitles[index])")
                                .font(.title)
                                .tag(index)
                        }
                        .ignoresSafeArea(edges: .bottom)
                    }
                }
                .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
                .indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .never))
            }
            
            
        })
        .ignoresSafeArea(edges: .bottom)
        .onChange(of: selectedTabIndex) { oldValue, newValue in
            withAnimation {
                selectedTabIndex = newValue
                selectedTabID = newValue
            }
        }
    }
}

#Preview {
    ContentView()
}

移动端
Swift
License:  CC BY 4.0
Share

Further Reading

May 19, 2024

复刻iOS圆环时间选择器

通过SwiftUI复刻iOS圆环时间选择器 Replicating iOS circular time picker with SwiftUI

May 8, 2024

打造可滑动切换的顶部TabBar

在SwiftUI应用中,实现一个带有可滑动切换的顶部TabBar是一个常见的需求。本文将介绍如何使用SwiftUI创建一个具有这种功能的界面。

Apr 27, 2024

SwiftUI与Alamofire结合:表单的POST提交

在本篇博客中,我们将详细介绍如何在SwiftUI中创建一个表单,并使用Alamofire库来处理表单的提交功能。这是一个极好的实例,帮助初学者了解SwiftUI界面构建与网络通信的整合应用。

OLDER

Java Lambda表达式:让你的代码像喝了红牛一样飞起来!

NEWER

复刻iOS圆环时间选择器

Recently Updated

  • iptables规则持久化
  • Win11的OOBE阶段启用Administrator账户并跳过账户创建步骤
  • 复刻iOS圆环时间选择器
  • 打造可滑动切换的顶部TabBar
  • Java Lambda表达式:让你的代码像喝了红牛一样飞起来!

Trending Tags

iOS HTML macOS Redis Java JS Swift Windows Linux JDK

Contents

©2025 Charlie的博客. Some rights reserved.

Using the Halo theme Chirpy