SwiftUI偏移TabView的分页指示器
SwiftUI偏移TabView的分页指示器

SwiftUI偏移TabView的分页指示器

在 SwiftUI 的 TabView 中,使用 .tabViewStyle(PageTabViewStyle(indexDisplayMode: .always)) 会自动显示分页指示器(圆点),但 SwiftUI 没有提供直接修改分页指示器位置或偏移的官方 API。

有一个变通方式是:把 TabView 包在一个 VStack 里,自定义分页指示器的位置,如下所示。

struct ContentView: View {
    @State private var selectedIndex = 0
    let pages = ["Page 1", "Page 2", "Page 3"]

    var body: some View {
        VStack {
            TabView(selection: $selectedIndex) {
                ForEach(pages.indices, id: \.self) { index in
                    Text(pages[index])
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .background(Color.orange)
                        .tag(index)
                }
            }
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) // 禁用默认指示器
            .frame(height: 140)
            .background(Color.red)

            // 自定义分页指示器,偏移位置
            HStack(spacing: 8) {
                ForEach(pages.indices, id: \.self) { index in
                    Circle()
                        .fill(index == selectedIndex ? Color.white : Color.gray)
                        .frame(width: 8, height: 8)
                }
            }
        }
        .padding(.vertical,10)
        .background(.purple)
    }
}

使用 .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) 禁用系统自带的分页指示器。

自己手动添加一个 HStack 放圆点。

用 @State 跟踪当前页码。

通过自定义分页指示器,可以实现偏移TabView分页指示器的效果。

实际应用

在实际应用中,可以使用tag直接绑定@State变量,并设置自定义分页指示器:

@State private var selectedIndex = 0

TabView(selection: $selectedIndex) {
    // 外币,更新时间,折算,统计
    HStack {}
        .tag(0)
    
    // 数字货币、大宗商品
    VStack {}
        .tag(1)
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.frame(height:160)
// 自定义分页指示器,偏移位置
HStack(spacing: 8) {
    ForEach(0...1, id: \.self) { index in
        Circle()
            .fill(index == selectedIndex ? Color.gray : Color.white)
            .frame(width: 8, height: 8)
            .overlay(
                Circle()
                    .stroke(Color.gray, lineWidth: 1)

    }
}

之所以在自定义分页指示器中使用overlay,是因为.fill()和.stroke()存在冲突,相关可见文章《SwiftUI关于fill()和stroke()组合方式导致无效视图报错问题

相关文章

1、SwiftUI指定TabView样式的tabViewStyle:https://fangjunyu.com/2025/01/16/swiftui%e6%8c%87%e5%ae%9atabview%e6%a0%b7%e5%bc%8f%e7%9a%84tabviewstyle/

2、SwiftUI关于fill()和stroke()组合方式导致无效视图报错问题:https://fangjunyu.com/2025/04/30/swiftui%e5%85%b3%e4%ba%8efill%e5%92%8cstroke%e7%bb%84%e5%90%88%e6%96%b9%e5%bc%8f%e5%af%bc%e8%87%b4%e6%97%a0%e6%95%88%e8%a7%86%e5%9b%be%e6%8a%a5%e9%94%99%e9%97%ae%e9%a2%98/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注