ios - 在 SwiftUI 中滚动时隐藏视图的动画
问题描述
我正在尝试在滚动时隐藏自定义 SearchBar 的动画,尽管它可以是任何视图。就像 Instagram 在他们的发现页面和许多其他应用程序上所做的那样。我找到了一些关于如何做到这一点的资源: UiKit 部分解决方案, SwiftUI 部分解决方案
我使用这些资源创建了两个代码示例,但它们并不能完全满足我的要求。
import SwiftUI
struct DiscoverView: View {
@State var textList: [String] = [
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text"
]
@State var initialOffset: CGFloat?
@State var offset: CGFloat?
var body: some View {
NavigationView {
VStack(alignment: .leading, spacing: 0) {
RoundedRectangle(cornerRadius: 10)
.frame(maxHeight: CGFloat(50) - CGFloat((initialOffset ?? 0) / 5) + CGFloat((offset ?? 0) / 5))
.opacity(Double(1) - Double((initialOffset ?? 0) / 100) + Double((offset ?? 0) / 100))
.edgesIgnoringSafeArea(.all))
ScrollView {
GeometryReader { geometry in
Color.clear.preference(key: OffsetKey.self, value: geometry.frame(in: .global).minY)
.frame(height: 0)
}
ForEach(textList, id: \.self) { text in
Text(text)
.font(.title)
}
}
Spacer()
}
.navigationBarHidden(true)
.onPreferenceChange(OffsetKey.self) {
if self.initialOffset == nil || self.initialOffset == 0 {
self.initialOffset = $0
}
self.offset = $0
}
}
}
}
struct OffsetKey: PreferenceKey {
static let defaultValue: CGFloat? = nil
static func reduce(value: inout CGFloat?,
nextValue: () -> CGFloat?) {
value = value ?? nextValue()
}
}
这个动画是想要的,但如果用户停止滚动,我希望 SearchBar (RoundedRectangle) 完全显示或完全隐藏,现在它保持半显示(这意味着可能以编程方式滚动直到视图被隐藏/显示)
import SwiftUI
struct DiscoverView: View {
@State var textList: [String] = [
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text",
"Some text",
"Another text"
]
@State var initialOffset: CGFloat?
@State var offset: CGFloat?
@State var viewIsShown: Bool = true
var body: some View {
NavigationView {
VStack(alignment: .leading, spacing: 0) {
if viewIsShown {
RoundedRectangle(cornerRadius: 10)
.frame(maxHeight: 50)
// .opacity(Double(1) - Double((initialOffset ?? 0) / 100) + Double((offset ?? 0) / 100))
.transition(.asymmetric(insertion: .opacity , removal: .opacity))
}
ScrollView {
GeometryReader { geometry in
Color.clear.preference(key: OffsetKey.self, value: geometry.frame(in: .global).minY)
.frame(height: 0)
}
ForEach(textList, id: \.self) { text in
Text(text)
.font(.title)
}
}
Spacer()
}
.navigationBarHidden(true)
.onPreferenceChange(OffsetKey.self) {
if self.initialOffset == nil || self.initialOffset == 0 {
self.initialOffset = $0
}
self.offset = $0
guard let initialOffset = self.initialOffset,
let offset = self.offset else {
return
}
if(initialOffset > offset){
withAnimation {
self.viewIsShown = false
}
} else {
withAnimation {
self.viewIsShown = true
}
}
}
}
}
}
这是使用默认动画的另一种尝试,但我希望视图在滚动时动画并仅在用户停止滚动或滚动偏移使视图处于一致状态(隐藏/显示)时完全隐藏/显示,而不是应用在特定偏移处立即为视图设置动画的过渡。
解决方案
推荐阅读
- python - 通过python连接数据库
- javascript - Promise#all 与顺序等待 - 时间分辨率的差异
- android - MapsActivity底部如何添加progressBar和textView
- java - Android中的字符串到日期对象
- python - 将 python 脚本应用于 git 历史记录中的每个提交
- powershell - 像函数一样执行字节
- spring - Spring Boot 尝试创建从项目中删除的类
- python - Python os.path.exists(r"%SystemDrive%\Users\{username}\Documents")
- macos - MacOS 上 Spyder 编辑器中 Cython 单元的问题
- c++ - 为什么我的函数返回的数字类似于 (-33686016),但没有返回所需的值?