Pau*_*aul 11 ios tabview swift swiftui pagetabviewstyle
我正在使用 SwiftUI 2 并使用 TabView 和 PageTabViewStyle。
现在,我正在寻找一种方法来“逗弄”与当前页面相邻的页面,如下所示:
用TabView和PageTabViewStyle可以实现这种效果吗?
我已经尝试将 TabView 的宽度减小为windowWidth-50。然而,这并没有导致相邻页面在侧面可见。50px相反,此更改在右窗口边框左侧引入了硬垂直边缘,新页面将滑入其中。
这是一个简单的实现。您可以将结构与 AnyView 数组一起使用,或直接在您自己的实现中使用逻辑。
struct ContentView: View {
@State private var selected = 4
var body: some View {
// the trailing closure takes an Array of AnyView type erased views
TeasingTabView(selectedTab: $selected, spacing: 20) {
[
AnyView(TabContentView(title: "First", color: .yellow)),
AnyView(TabContentView(title: "Second", color: .orange)),
AnyView(TabContentView(title: "Fourth", color: .green)),
AnyView(TabContentView(title: "Fifth", color: .blue)),
AnyView(
Image(systemName: "lizard")
.resizable().scaledToFit()
.padding()
.frame(maxHeight: .infinity)
.border(.red)
)
]
}
}
}
struct TeasingTabView: View {
@Binding var selectedTab: Int
let spacing: CGFloat
let views: () -> [AnyView]
@State private var offset = CGFloat.zero
var viewCount: Int { views().count }
var body: some View {
VStack(spacing: spacing) {
GeometryReader { geo in
let width = geo.size.width * 0.7
LazyHStack(spacing: spacing) {
Color.clear
.frame(width: geo.size.width * 0.15 - spacing)
ForEach(0..<viewCount, id: \.self) { idx in
views()[idx]
.frame(width: width)
.padding(.vertical)
}
}
.offset(x: CGFloat(-selectedTab) * (width + spacing) + offset)
.animation(.easeOut, value: selectedTab)
.gesture(
DragGesture()
.onChanged { value in
offset = value.translation.width
}
.onEnded { value in
withAnimation(.easeOut) {
offset = value.predictedEndTranslation.width
selectedTab -= Int((offset / width).rounded())
selectedTab = max(0, min(selectedTab, viewCount-1))
offset = 0
}
}
)
}
//
HStack {
ForEach(0..<viewCount, id: \.self) { idx in
Circle().frame(width: 8)
.foregroundColor(idx == selectedTab ? .primary : .secondary.opacity(0.5))
.onTapGesture {
selectedTab = idx
}
}
}
}
}
}
struct TabContentView: View {
let title: String
let color: Color
var body: some View {
Text(title).font(.title)
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(color.opacity(0.4), ignoresSafeAreaEdges: .all)
.clipShape(RoundedRectangle(cornerRadius: 20))
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1378 次 |
| 最近记录: |