在SwiftUI中按百分比跟踪视图可见性

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

Track view visibility by percentage in SwiftUI

问题

我正在尝试获取ExampleView的可见百分比。我尝试了下面的方法,你可以在代码中看到。更精确地说,当ExampleView变得可见时,它将开始计算该视图的可见百分之多少。

struct ContentView: View {
    var body: some View {
        NavigationView {
            
            List {
                ForEach(1..<20) { index in
                    
                    if index % 5 == 0 {
                        VStack {
                            ExampleView()
                                .onPreferenceChange(BoundsPreferenceKey.self) { value in
                                    print(value as Any)
                                }
        
                        }
                        .frame(minHeight: 500)
                    } else {
                        Rectangle()
                            .fill(.blue)
                            .frame(minHeight: 300)
                    }
                }
            }
        }
    }
}

struct BoundsPreferenceKey: PreferenceKey {
    
    typealias Value = Anchor<CGRect>?
    static var defaultValue: Value = nil
    
    static func reduce(
        value: inout Value,
        nextValue: () -> Value
    ) {
        value = nextValue()
    }
}

struct ExampleView: View {
    
    var body: some View {
        ZStack {
            Color.yellow
            Text("Hello World !!!")
                .anchorPreference(
                    key: BoundsPreferenceKey.self,
                    value: .bounds
                ) { $0 }
        }
        .overlayPreferenceValue(BoundsPreferenceKey.self) { preferences in
            GeometryReader { geometry in
                preferences.map {
                    Rectangle()
                        .stroke()
                        .frame(
                            width: geometry[$0].width,
                            height: geometry[$0].height
                        )
                        .offset(
                            x: geometry[$0].minX,
                            y: geometry[$0].minY
                        )
                }
            }
        }
    }
}

在overlayPreferenceValue(offset)每次调用时,ExampleView的框架发生更改。然而,我不知道如何获得这些百分比。如果您有其他建议,请告诉我。

请帮助我获取可见百分比。如果您需要更多信息,请告诉我。

提前感谢。

英文:

I am trying to get visibility percentage of the ExampleView. I tried below things which you can see in code. To more precise word when ExampleView become visible it's going start counting how many percent of that view is visible.

struct ContentView: View {
    var body: some View {
    NavigationView {
        
        List {
            ForEach(1..&lt;20) { index in
                
                if index%5 == 0 {
                    VStack {
                        ExampleView()
                            .onPreferenceChange(BoundsPreferenceKey.self) { value in
                                print(value as Any)
                            }
    
                    }
                    .frame(minHeight: 500)
                }else {
                    Rectangle()
                        .fill(.blue)
                        .frame(minHeight: 300)
                }
            }
        }
    }
  }
}

struct BoundsPreferenceKey: PreferenceKey {

    typealias Value = Anchor&lt;CGRect&gt;?
    static var defaultValue: Value = nil

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

struct ExampleView: View {

  var body: some View {
    ZStack {
        Color.yellow
        Text(&quot;Hello World !!!&quot;)
            .anchorPreference(
                key: BoundsPreferenceKey.self,
                value: .bounds
            ) { $0 }
    }
    .overlayPreferenceValue(BoundsPreferenceKey.self) { preferences in
        GeometryReader { geometry in
            preferences.map {
                Rectangle()
                    .stroke()
                    .frame(
                        width: geometry[$0].width,
                        height: geometry[$0].height
                    )
                    .offset(
                        x: geometry[$0].minX,
                        y: geometry[$0].minY
                    )
            }
        }
    }
  }
}

On overlayPreferenceValue(offset) calling every time when its frame of ExampleView is changing. However I don't how get those percentage. If you any other suggestion please let me know.

Please help me to get visibility percentage. Please let me know if you need more information about it.

Thanks in advance.

答案1

得分: 1

这里我找到了我的答案。如果您有更好的解决方案或建议,请在评论中提出或进行编辑。

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            
            VStack {
                Rectangle()
                    .fill(.green)
                    .frame(minHeight: 300)
                List {
                    ForEach(1..<20) { index in
                        
                        if index % 5 == 0 {
                            VStack {
                                CustomView()
                            }
                            .frame(minHeight: 300)
                        } else {
                            Rectangle()
                                .fill(.blue)
                                .frame(minHeight: 300)
                        }
                    }
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct CustomView: View {
    
    var body: some View {
        Image("Monitor")
            .resizable()
            .background(Color.red)
            .aspectRatio(contentMode: .fill)
            .overlay(
                GeometryReader { geo in
                    Color.clear
                        .onAppear() {
                            self.getPercentage(geo: geo, heightOfAdView: 300)
                        }
                        .onChange(of: geo.frame(in: .global)) { _ in
                            self.getPercentage(geo: geo, heightOfAdView: 300)
                        }
                }
            )
    }
    
    func getPercentage(geo: GeometryProxy, heightOfAdView: CGFloat) {
        let screenHeight = UIScreen.main.bounds.height
        let yAxisOfAdView = geo.frame(in: .global).origin.y
        let visiblityInPx = screenHeight - yAxisOfAdView
        let visiblePCT = (visiblityInPx * 100.0) / heightOfAdView
        print("screenHeight:- \(screenHeight)")
        print("yAxisOfAdView:- \(yAxisOfAdView)")
        print("visiblityInPx:- \(visiblityInPx)")
        visiblePCT <= 100 ? print("visiblePCT:- \(visiblePCT)") : print("visiblePCT:- 100")
    }
}

如果您需要进一步的帮助,请告诉我。

英文:

Here I found my answer. If you have any better solution or suggestion, Please comment on it or edit it.

import SwiftUI

struct ContentView: View {
var body: some View {
    NavigationView {
        
        VStack {
            Rectangle()
                .fill(.green)
                .frame(minHeight: 300)
            List {
                ForEach(1..&lt;20) { index in
                    
                    if index%5 == 0 {
                        VStack {
                            CustomView()
                        }
                        .frame(minHeight: 300)
                    }else {
                        Rectangle()
                            .fill(.blue)
                            .frame(minHeight: 300)
                    }
                }
            }
        }
    }
  }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}

struct CustomView: View {

  var body: some View {
    Image(&quot;Monitor&quot;)
        .resizable()
        .background(Color.red)
        .aspectRatio(contentMode: .fill)
        .overlay(
            GeometryReader { geo in
                Color.clear
                    .onAppear() {
                        self.getPercentage(geo: geo, heightOfAdView: 300)
                    }
                    .onChange(of: geo.frame(in: .global)) { _ in
                        self.getPercentage(geo: geo, heightOfAdView: 300)
                    }
            }
        )
}

func getPercentage(geo: GeometryProxy,heightOfAdView: CGFloat) {
    let screenHeight = UIScreen.main.bounds.height
    let yAxisOfAdView = geo.frame(in: .global).origin.y
    let visiblityInPx = screenHeight - yAxisOfAdView
    let visiblePCT = (visiblityInPx * 100.0)/heightOfAdView
    print(&quot;screenHeight:- \(screenHeight)&quot;)
    print(&quot;yAxisOfAdView:- \(yAxisOfAdView)&quot;)
    print(&quot;visiblityInPx:- \(visiblityInPx)&quot;)
    visiblePCT &lt;= 100 ? print(&quot;visiblePCT:- \(visiblePCT)&quot;) :       print(&quot;visiblePCT:- 100&quot;)
  }
}

huangapple
  • 本文由 发表于 2023年3月7日 22:56:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/75663595.html
匿名

发表评论

匿名网友

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

确定