Ios 当滚动超过工作表中的限制时,防止在滚动视图顶部的图像上方填充
如果在ScrollView中呈现一张在下方显示文本的图纸,则向下滚动然后向上轻弹时,请注意,它将滚动超过限制,并且在图像上方显示空白,直到弹性滚动效果稳定为止。然后,您可以向下拉以关闭该工作表 我想防止在ScrollView中的图像上方添加空间。相反,我希望填充显示在图像和第一个文本之间。应用商店就是这样一个应用程序——当你点击今天的一篇报道时,请注意,当向上滚动超过限制时,顶部的图像始终固定在顶部,并且在其下方会出现弹性反弹效果 我怀疑GeometryReader可以用来获得全球坐标空间中的位置,但我不清楚如何利用它来获得所需的行为Ios 当滚动超过工作表中的限制时,防止在滚动视图顶部的图像上方填充,ios,swiftui,Ios,Swiftui,如果在ScrollView中呈现一张在下方显示文本的图纸,则向下滚动然后向上轻弹时,请注意,它将滚动超过限制,并且在图像上方显示空白,直到弹性滚动效果稳定为止。然后,您可以向下拉以关闭该工作表 我想防止在ScrollView中的图像上方添加空间。相反,我希望填充显示在图像和第一个文本之间。应用商店就是这样一个应用程序——当你点击今天的一篇报道时,请注意,当向上滚动超过限制时,顶部的图像始终固定在顶部,并且在其下方会出现弹性反弹效果 我怀疑GeometryReader可以用来获得全球坐标空间中的位
struct details视图:视图{
var图像:UIImage?
var body:一些观点{
滚动视图{
图像(uiImage:Image??uiImage())
.可调整大小()
.aspectRatio((图像?.size.width±1)/(图像?.size.height±1),内容模式:。填充)
.背景(颜色(.secondarySystemFill))
ForEach(0..这可以使用GeometryReader:
将图像
包装在GeometryReader
中,这样就可以获得全局坐标空间中的位置
确保将.scaledToFill()
添加到GeometryReader
中,否则它不会占用滚动视图中的任何空间。或者,您可以通过为GeometryReader
提供默认帧来解决此问题
使用全局坐标空间中图像的minY
设置“向上拖动”时的offset
。这样可以模拟图像处于固定位置
这项技术有一个问题。当向下拖动工作表时,图像会粘在它的位置上,这看起来很奇怪。我还不知道如何解决这个问题,但这个答案可能会对您有所帮助
请参见下面的示例
struct DetailsView: View {
func getOffsetY(basedOn geo: GeometryProxy) -> CGFloat {
// Find Y position
let minY = geo.frame(in: .global).minY
let emptySpaceAboveSheet: CGFloat = 40
// Don't offset view when scrolling down
if minY <= emptySpaceAboveSheet {
return 0
}
// Offset the view when it goes above to simulate it standing still
return -minY + emptySpaceAboveSheet
}
var body: some View {
ScrollView {
GeometryReader { imageGeo in
Image(systemName: "option")
.resizable()
.scaledToFill()
.background(Color(.secondarySystemFill))
.offset(x: 0, y: self.getOffsetY(basedOn: imageGeo))
}
// Need this to make sure the geometryreader has a size
.scaledToFill()
ForEach(0..<50) { index in
Text("\(index)")
}
}
}
}
struct details视图:视图{
func getOffsetY(基于geo:GeometryProxy)->CGFloat{
//找到Y位置
设minY=geo.frame(in:.global).minY
让空白空间位于图纸上方:CGFloat=40
//向下滚动时不偏移视图
如果minYOk,下面是您案例的可能解决方案。使用Xcode 12b5/iOS 14进行测试
这个想法是有一个内部的容器,在里面滚动,但是在滚动视图坐标空间中读取它的坐标,补偿相对于容器的图像位置偏移,容器继续滚动,这样就产生了效果,所有其他的东西,比如图像下面,仍然有弹跳
struct DemoView:View{
var图像:UIImage?
@国家私有风险值偏移量=CGFloat.zero
var body:一些观点{
滚动视图{
VStack{//内部容器
图像(uiImage:Image??uiImage())
.可调整大小()
.aspectRatio((图像?.size.width±1)/(图像?.size.height±1),内容模式:。填充)
.背景(颜色(.secondarySystemFill))
.offset(y:offset<0?offset:0)//压缩偏移
ForEach(0..Value){
value+=nextValue()
}
}
这几乎可以正常工作!就像您提到的那样,在工作表关闭时,图像保持不变,并且图像纵横比丢失。您不想按照中所述禁用反弹吗?虽然这样可以解决不希望出现的行为,但希望仍然支持弹性滚动行为,而不是在顶部突然停止滚动
struct DetailsView: View {
var image: UIImage?
var body: some View {
ScrollView {
Image(uiImage: image ?? UIImage())
.resizable()
.aspectRatio((image?.size.width ?? 1) / (image?.size.height ?? 1), contentMode: .fill)
.background(Color(.secondarySystemFill))
ForEach(0..<50) { index in
Text("\(index)")
}
}
}
}
struct DetailsView: View {
func getOffsetY(basedOn geo: GeometryProxy) -> CGFloat {
// Find Y position
let minY = geo.frame(in: .global).minY
let emptySpaceAboveSheet: CGFloat = 40
// Don't offset view when scrolling down
if minY <= emptySpaceAboveSheet {
return 0
}
// Offset the view when it goes above to simulate it standing still
return -minY + emptySpaceAboveSheet
}
var body: some View {
ScrollView {
GeometryReader { imageGeo in
Image(systemName: "option")
.resizable()
.scaledToFill()
.background(Color(.secondarySystemFill))
.offset(x: 0, y: self.getOffsetY(basedOn: imageGeo))
}
// Need this to make sure the geometryreader has a size
.scaledToFill()
ForEach(0..<50) { index in
Text("\(index)")
}
}
}
}
struct DemoView: View {
var image: UIImage?
@State private var offset = CGFloat.zero
var body: some View {
ScrollView {
VStack { // internal container
Image(uiImage: image ?? UIImage())
.resizable()
.aspectRatio((image?.size.width ?? 1) / (image?.size.height ?? 1), contentMode: .fill)
.background(Color(.secondarySystemFill))
.offset(y: offset < 0 ? offset : 0) // compansate offset
ForEach(0..<50) { index in
Text("\(index)")
}
}
.background(GeometryReader {
// read current position of container inside scroll view
Color.clear.preference(key: ViewOffsetKey.self,
value: -$0.frame(in: .named("scroll")).origin.y)
})
.onPreferenceChange(ViewOffsetKey.self) {
self.offset = $0 // needed offset to shift back image
}
}
.coordinateSpace(name: "scroll")
}
}
struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}