Если я просто помещу ваш Webview
в VStack
, то он будет иметь размеры, как ожидается. Там нет никаких реальных проблем.
Хотя вы не заявили об этом, наиболее вероятная причина того, что ваш Webview
не занимает никакого места, состоит в том, что вы поместили эти элементы в ScrollView
. Поскольку WKWebView
в основном (хотя и не является подклассом) UIScrollView
, система не знает, как его размер, если он содержится в другом представлении прокрутки.
Например:
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView { // THIS LINE means that...
VStack(spacing: 0.0) {
Color.red.aspectRatio(1.0, contentMode: .fill)
Text("Lorem ipsum dolor sit amet").fontWeight(.bold)
Webview()
.frame(height: 300) // ...THIS is necessary
}
}
.navigationBarItems(leading: Text("Item"))
.navigationBarTitle("", displayMode: .inline)
}
}
}
Вложенные прокрутки - это не то, что вам нужно для макета, который вы показали в любом случае. Вы, несомненно, хотите, чтобы изображение и текст вверху прокручивались, когда прокручивается WKWebView
.
Техника, которую вы должны использовать с UIKit или SwiftUI, будет похожей. Я действительно не рекомендую делать это с SwiftUI на этом этапе.
- Поместите
WKWebView
в контейнер (наиболее вероятно UIViewController.view
) - Поместите содержимое заголовка (изображение плюс текст, который может быть в
UIHostingContainer
) в этом представлении в виде родного брата над веб-представлением. - Установите для
webView.scrollView.contentInset.top
размер вашего контента от # 2 - Реализация
UIScrollViewDelegate.scrollViewDidScroll()
- В
scrollViewDidScroll
измените положение своего контента, чтобы оно соответствовало contentOffset
.
Вот одна из возможных реализаций:
WebView:
import SwiftUI
import WebKit
struct WebView : UIViewRepresentable {
@Binding var offset: CGPoint
var contentInset: UIEdgeInsets = .zero
class Coordinator: NSObject, UIScrollViewDelegate {
var parent: WebView
init(_ parent: WebView) {
self.parent = parent
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
var offset = scrollView.contentOffset
offset.y += self.parent.contentInset.top
self.parent.offset = offset
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> WKWebView {
let webview = WKWebView()
webview.scrollView.delegate = context.coordinator
// continue setting up webview content
return webview
}
func updateUIView(_ uiView: WKWebView, context: Context) {
if uiView.scrollView.contentInset != self.contentInset {
uiView.scrollView.contentInset = self.contentInset
}
}
}
ContentView. Примечание: я использовал 50
в качестве константы вместо расчета размера. Можно получить фактический размер, используя GeometryReader
, хотя.
struct ContentView: View {
@State var offset: CGPoint = .zero
var body: some View {
NavigationView {
WebView(offset: self.$offset, contentInset: UIEdgeInsets(top: 50, left: 0, bottom: 0, right: 0))
.overlay(
Text("Hello World!")
.frame(height: 50)
.offset(y: -self.offset.y)
, alignment: .topLeading)
.edgesIgnoringSafeArea(.all)
}
.navigationBarItems(leading: Text("Item"))
.navigationBarTitle("", displayMode: .inline)
}
}