swift - 如何防止我的 SwiftUI 视图在滚动时调整大小
问题描述
我希望有人能指出我正确的方向——我一直在试验 SwiftUI,我创建了一个类似于 Twitter Profile UI 的视图。
当标题崩溃时,我似乎有一个奇怪的效果。
有一个“最佳位置”,其中标题被折叠并且标签栏在滚动视图包含在标题下滚动之前调整了少量大小。
你可以在这个视频中看到。
我根本不希望选项卡段调整大小,而是在标题折叠后它应该保持原位并且滚动视图应该在它下面自由移动。
我确定我遗漏了一些明显的东西,但是一些新鲜的眼睛可能正是我需要的帮助。
对此的任何想法将不胜感激!
import SwiftUI
struct ContentView: View {
@State private var safeArea: EdgeInsets = EdgeInsets(.zero)
@State private var offset: CGFloat = 0
@State private var tabBarOffset: CGFloat = 0
@State var currentTab = "Tab #1"
@Namespace var animation
var body: some View {
GeometryReader { foo in
ScrollView {
VStack(spacing: 0) {
// Header
GeometryReader { proxy -> AnyView in
// Sticky Header
DispatchQueue.main.async {
offset = proxy.frame(in: .global).minY
safeArea = foo.safeAreaInsets
}
return AnyView(makeHeader())
}
.frame(height: 180)
.zIndex(1)
// Profile
VStack(spacing: 0) {
VStack(spacing: 0) {
HStack(spacing: 0) {
TabButton(title: "Tab #1", currentTab: $currentTab, animation: animation)
.frame(maxWidth: .infinity)
TabButton(title: "Tab #2", currentTab: $currentTab, animation: animation)
.frame(maxWidth: .infinity)
TabButton(title: "Tab #3", currentTab: $currentTab, animation: animation)
.frame(maxWidth: .infinity)
}
Divider()
}
.padding(.top, 20)
.background(Color.white)
.offset(y: tabBarOffset < 90 ? -tabBarOffset + 90 : 0)
.overlay(
GeometryReader { proxy -> Color in
DispatchQueue.main.async {
tabBarOffset = proxy.frame(in: .global).minY
}
return Color.clear
}
.frame(width: 0, height: 0),
alignment: .top
)
.zIndex(1)
VStack {
ForEach((0..<50)) {
Text("Row #\($0)")
Divider()
}
}
.padding(.top)
.zIndex(0)
}
}
}
.ignoresSafeArea(.all, edges: .top)
}
}
@ViewBuilder func makeHeader() -> some View {
ZStack {
// Cover
Color.gray
.frame(maxWidth: .infinity)
.frame(height: offset > 0 ? 180 + offset : 180)
}
.clipped()
// Stretchy Effect
.frame(height: offset > 0 ? 180 + offset : nil)
.offset(y: offset > 0 ? -offset : -offset < 80 ? 0 : -offset - 80)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct TabButton: View {
var title: String
@Binding var currentTab: String
var animation: Namespace.ID
var body: some View {
Button(
action: {
withAnimation { currentTab = title }
},
label: {
LazyVStack(spacing: 12) {
Text(title)
.fontWeight(.semibold)
.foregroundColor(currentTab == title ? .blue : .gray)
.padding(.horizontal)
if currentTab == title {
Capsule()
.fill(Color.blue)
.frame(height: 1.2)
.matchedGeometryEffect(id: "TAB", in: animation)
} else {
Capsule()
.fill(Color.clear)
.frame(height: 1.2)
}
}
}
)
}
}
解决方案
在这里,设置 90 而不是 80。作为设置顶部选项卡视图的 y 偏移量 90,您的整个逻辑基于 90 值。
@ViewBuilder func makeHeader() -> some View {
ZStack {
// Cover
Color.red
.frame(maxWidth: .infinity)
.frame(height: offset > 0 ? 180 + offset : 180)
}
.clipped()
// Stretchy Effect
.frame(height: offset > 0 ? 180 + offset : nil)
.offset(y: offset > 0 ? -offset : -offset < 90 ? 0 : -offset - 90) //<=== Here
}
推荐阅读
- json - WSO2 - 将字段添加到现有的 json
- r - 如何在国家边界内乘以栅格的像元值
- javascript - 如何从 vue 3 设置函数返回 watchEffect 中的变量
- html - 使弹性项目占据溢出容器的全部高度
- ios - 键盘显示iOS15后UITableViewCell删除
- wpf - 具有不同文本对齐方式的工具提示 DataGridCell
- c# - IOrderedEnumerable
' 不包含 'WithPrevious' 的定义 - node.js - 如何使用 mongodb 将多条记录更新到某个限制
- javascript - 如何在 ReactJS 中访问功能组件中的状态?
- qiskit - 如何让qiskit打印一个量子门的真值表?