我有一个如下的视图。我想知道它是否是屏幕上显示的视图。有什么功能可以实现这个功能吗?
struct TestView: View { var body: some View { Text("Test View") } }
lf3rwulv1#
您可以在符合View协议的任何类型的视图上使用onAppear。
struct TestView: View { @State var isViewDisplayed = false var body: some View { Text("Test View") .onAppear { self.isViewDisplayed = true } .onDisappear { self.isViewDisplayed = false } } func someFunction() { if isViewDisplayed { print("View is displayed.") } else { print("View is not displayed.") } } }
PS:虽然这个解决方案涵盖了大多数情况,但它有许多边缘情况没有涵盖。当苹果发布更好的解决方案时,我会更新这个答案。
5lwkijsr2#
可以使用GeometryReader和GeometryProxy检查视图在全局范围内的位置。
struct CustomButton: View { var body: some View { GeometryReader { geometry in VStack { Button(action: { }) { Text("Custom Button") .font(.body) .fontWeight(.bold) .foregroundColor(Color.white) } .background(Color.blue) }.navigationBarItems(trailing: self.isButtonHidden(geometry) ? HStack { Button(action: { }) { Text("Custom Button") } : nil) } } private func isButtonHidden(_ geometry: GeometryProxy) -> Bool { // Alternatively, you can also check for geometry.frame(in:.global).origin.y if you know the button height. if geometry.frame(in: .global).maxY <= 0 { return true } return false }
k5hmc34c3#
正如Oleg所提到的,根据您的用例,onAppear的一个可能问题是,只要View在视图层次结构中,它的action就会被执行,而不管该视图是否对用户可能可见。我的用例是在视图实际可见时延迟加载内容,我不想依赖于封装在LazyHStack或类似文件中的视图。为了实现这一点,我在View中添加了一个扩展onBecomingVisible,它具有与onAppear相同的API,但仅当视图first与屏幕的可见边界相交时才调用该操作,之后不会调用该操作。
onAppear
View
action
LazyHStack
onBecomingVisible
public extension View { func onBecomingVisible(perform action: @escaping () -> Void) -> some View { modifier(BecomingVisible(action: action)) } } private struct BecomingVisible: ViewModifier { @State var action: (() -> Void)? func body(content: Content) -> some View { content.overlay { GeometryReader { proxy in Color.clear .preference( key: VisibleKey.self, // See discussion! value: UIScreen.main.bounds.intersects(proxy.frame(in: .global)) ) .onPreferenceChange(VisibleKey.self) { isVisible in guard isVisible, let action else { return } action() action = nil } } } } struct VisibleKey: PreferenceKey { static var defaultValue: Bool = false static func reduce(value: inout Bool, nextValue: () -> Bool) { } } }
讨论我对在代码中使用UIScreen.main.bounds并不感到兴奋!也许可以使用几何代理来代替,或者使用一些@Environment值--尽管我还没有考虑过这个问题。
UIScreen.main.bounds
@Environment
3条答案
按热度按时间lf3rwulv1#
您可以在符合View协议的任何类型的视图上使用onAppear。
PS:虽然这个解决方案涵盖了大多数情况,但它有许多边缘情况没有涵盖。当苹果发布更好的解决方案时,我会更新这个答案。
5lwkijsr2#
可以使用GeometryReader和GeometryProxy检查视图在全局范围内的位置。
k5hmc34c3#
正如Oleg所提到的,根据您的用例,
onAppear
的一个可能问题是,只要View
在视图层次结构中,它的action
就会被执行,而不管该视图是否对用户可能可见。我的用例是在视图实际可见时延迟加载内容,我不想依赖于封装在
LazyHStack
或类似文件中的视图。为了实现这一点,我在
View
中添加了一个扩展onBecomingVisible
,它具有与onAppear
相同的API,但仅当视图first与屏幕的可见边界相交时才调用该操作,之后不会调用该操作。讨论
我对在代码中使用
UIScreen.main.bounds
并不感到兴奋!也许可以使用几何代理来代替,或者使用一些@Environment
值--尽管我还没有考虑过这个问题。