如何在SwiftUI中预览嵌套的ScrollView,而不受可刷新修饰符的影响

huangapple go评论68阅读模式
英文:

How to preview nested ScrollView from picking up refreshable modifier in SwiftUI

问题

如果我使父级的ScrollView可刷新,任何其他嵌套的ScrollView也将执行相同的可刷新操作。有没有办法阻止这种行为?这里是一个示例。

struct ContentView: View {
    @State var showSheet = false
    var body: some View {
        ScrollView {
            VStack {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundColor(.accentColor)
                Button("Hello, world!") {
                    showSheet = true
                }
            }
            .padding()
        }
        .sheet(isPresented: $showSheet) {
            ScrollView {
                VStack {
                    Image(systemName: "globe")
                        .imageScale(.large)
                        .foregroundColor(.accentColor)
                    Text("Hello, world!")
                }
                .padding()
            }
            .presentationDetents([.medium, .large])
        }
        .refreshable {
            
        }
    }
}
英文:

If I make a parent ScrollView refreshable any other nested ScrollView also will pickup the same refreshable action. Is there a way to prevent this behavior? Here is an example.

struct ContentView: View {
	@State var showSheet = false
    var body: some View {
		ScrollView {
			VStack {
				Image(systemName: "globe")
					.imageScale(.large)
					.foregroundColor(.accentColor)
				Button("Hello, world!") {
					showSheet = true
				}
			}
			.padding()
		}
		.sheet(isPresented: $showSheet) {
			ScrollView {
				VStack {
					Image(systemName: "globe")
						.imageScale(.large)
						.foregroundColor(.accentColor)
					Text("Hello, world!")
				}
				.padding()
			}
			.presentationDetents([.medium, .large])
		}
		.refreshable {
			
		}
    }
}

答案1

得分: 1

refreshable修饰符移动到sheet修饰符之前:

.refreshable {
    print("刷新")
}
.sheet(isPresented: $showSheet) {
    ScrollView {
        ...
    }
    .presentationDetents([.medium, .large])
}

refreshable只修改其上方的内容,因此不包括sheet

英文:

Move the refreshable modifier to before the sheet modifier:

.refreshable {
    print("Refreshed")
}
.sheet(isPresented: $showSheet) {
    ScrollView {
        ...
    }
    .presentationDetents([.medium, .large])
}

refreshable only modifies the things above it, so this excludes the sheet.

答案2

得分: -2

以下是您要的代码的翻译部分:

这里是一个示例,说明如何在下面的代码中实现不允许嵌套进行刷新操作:

   struct ContentView: View {
    @State var showSheet = false
    @State private var isParentRefreshing = false
    
    var body: some View {
        ScrollView {
            VStack {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundColor(.accentColor)
                Button("Hello, world!") {
                    showSheet = true
                }
            }
            .padding()
            .modifier(RefreshableModifier(isRefreshing: $isParentRefreshing))
        }
        .sheet(isPresented: $showSheet) {
            ScrollView {
                VStack {
                    Image(systemName: "globe")
                        .imageScale(.large)
                        .foregroundColor(.accentColor)
                    Text("Hello, world!")
                }
                .padding()
            }
            .presentationDetents([.medium, .large])
        }
        .refreshable {
            // 父级滚动视图刷新操作
            // 在这里放置您的刷新逻辑
        }
    }
}

struct RefreshableModifier: ViewModifier {
    @Binding var isRefreshing: Bool
    
    func body(content: Content) -> some View {
        content
            .overlay(
                GeometryReader { geometry in
                    if isRefreshing {
                        ProgressView()
                            .offset(y: -geometry.size.height)
                            .padding(.bottom, -geometry.size.height)
                    }
                }
            )
            .onPreferenceChange(RefreshablePreferenceKey.self) { isRefreshing = $0 }
            .gesture(
                DragGesture()
                    .onChanged { value in
                        if value.startLocation.y < 50 && value.translation.height > 50 {
                            isRefreshing = true
                        }
                    }
            )
    }
}

struct RefreshablePreferenceKey: PreferenceKey {
    static var defaultValue: Bool = false

    static func reduce(value: inout Bool, nextValue: () -> Bool) {
        value = nextValue()
    }
}

希望这可以帮助您!如果您有任何其他问题,请随时提出。

英文:

Here's an example of how you can achieve not letting the nested have refresh actions in the code below:

   struct ContentView: View {
    @State var showSheet = false
    @State private var isParentRefreshing = false
    
    var body: some View {
        ScrollView {
            VStack {
                Image(systemName: &quot;globe&quot;)
                    .imageScale(.large)
                    .foregroundColor(.accentColor)
                Button(&quot;Hello, world!&quot;) {
                    showSheet = true
                }
            }
            .padding()
            .modifier(RefreshableModifier(isRefreshing: $isParentRefreshing))
        }
        .sheet(isPresented: $showSheet) {
            ScrollView {
                VStack {
                    Image(systemName: &quot;globe&quot;)
                        .imageScale(.large)
                        .foregroundColor(.accentColor)
                    Text(&quot;Hello, world!&quot;)
                }
                .padding()
            }
            .presentationDetents([.medium, .large])
        }
        .refreshable {
            // Parent scroll view refresh action
            // Put your refresh logic here
        }
    }
}

struct RefreshableModifier: ViewModifier {
    @Binding var isRefreshing: Bool
    
    func body(content: Content) -&gt; some View {
        content
            .overlay(
                GeometryReader { geometry in
                    if isRefreshing {
                        ProgressView()
                            .offset(y: -geometry.size.height)
                            .padding(.bottom, -geometry.size.height)
                    }
                }
            )
            .onPreferenceChange(RefreshablePreferenceKey.self) { isRefreshing = $0 }
            .gesture(
                DragGesture()
                    .onChanged { value in
                        if value.startLocation.y &lt; 50 &amp;&amp; value.translation.height &gt; 50 {
                            isRefreshing = true
                        }
                    }
            )
    }
}

struct RefreshablePreferenceKey: PreferenceKey {
    static var defaultValue: Bool = false

    static func reduce(value: inout Bool, nextValue: () -&gt; Bool) {
        value = nextValue()
    }
}

huangapple
  • 本文由 发表于 2023年6月16日 09:35:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76486462.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定