ios - 如何让 SwiftUI View 扩大可用空间?
问题描述
我正在尝试使 SwiftUI 视图扩展其可用空间。我有一个使用 MapKit 在屏幕上显示地图的 MapView。我希望这张地图可以扩展 VStack 中的可用空间。您可以看到它位于红色视图上方和搜索栏下方。如果我使红色视图的高度为 100,则 MapView 会缩小。如果我没有在红色视图上设置高度,那么 MapView 会更大,但是红色视图看起来不像我想要的那样。
我希望红色视图的高度为 100,并且 MapView 填充搜索栏下方和红色视图上方的所有可用高度。
内容视图:
struct ContentView: View {
@ObservedObject
var viewModel: HomeViewModel
var body: some View {
NavigationView {
ZStack {
ColorTheme.brandBlue.value.edgesIgnoringSafeArea(.all)
VStack {
CardView {
EditText(hint: "Search", text: self.$viewModel.searchText, textContentType: UITextContentType.organizationName)
}
MapView(annotations: self.$viewModel.restaurantAnnotations)
.cornerRadius(8)
CardView(height: 100) {
HStack {
Color.red
}
}
}
}
.navigationBarTitle("", displayMode: .inline)
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
}
}
}
卡片视图
struct CardView<Content>: View where Content : View {
var height: CGFloat = .infinity
var content: () -> Content
var body: some View {
content()
.padding(EdgeInsets.init(top: 0, leading: 8, bottom: 8, trailing: 8))
.background(Color.white.cornerRadius(8))
.shadow(radius: 2, x: 0, y: 1)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: height)
}
}
编辑文本
struct EditText: View {
var hint: String
@Binding
var text: String
var label: String = ""
var textContentType: UITextContentType? = .none
var keyboardType: UIKeyboardType = .default
var textSize: CGFloat = 16
var body: some View {
return VStack(alignment: .leading) {
Text(label).font(.system(size: 12)).bold()
.foregroundColor(ColorTheme.text.value)
HStack {
TextField(hint, text: $text)
.lineLimit(1)
.font(.system(size: textSize))
.textContentType(textContentType)
.keyboardType(keyboardType)
.foregroundColor(ColorTheme.text.value)
}
Divider().background(ColorTheme.brandBlue.value)
}
}
}
地图视图
struct MapView: UIViewRepresentable {
@Binding
var annotations: [MKAnnotation]
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.delegate = context.coordinator
return mapView
}
func updateUIView(_ view: MKMapView, context: Context) {
view.delegate = context.coordinator
view.addAnnotations(annotations)
if annotations.count == 1 {
let coords = annotations.first!.coordinate
let region = MKCoordinateRegion(center: coords, span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
view.setRegion(region, animated: true)
}
}
func makeCoordinator() -> MapViewCoordinator {
MapViewCoordinator(self)
}
}
地图视图协调器
class MapViewCoordinator: NSObject, MKMapViewDelegate {
var mapViewController: MapView
init(_ control: MapView) {
self.mapViewController = control
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?{
//Custom View for Annotation
let identifier = "Placemark"
if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) {
annotationView.annotation = annotation
return annotationView
} else {
let annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView.isEnabled = true
annotationView.canShowCallout = true
let button = UIButton(type: .infoDark)
annotationView.rightCalloutAccessoryView = button
return annotationView
}
return nil
}
}
解决方案
这是一个解决方案(使用 Xcode 11.4 测试):
struct CardView<Content>: View where Content : View {
var height: CGFloat? = nil // << here !!
注意:定义的高度,即使使用.infinity
,通过向地图视图请求高度来使您的上卡等效,因此它们划分了可用空间;未指定高度时,组件紧贴内容