Ios UIKit中的可扩展SwiftUI视图垂直居中
我正在将一些新的SwiftUI视图集成到UIKit应用程序中,但遇到了一个问题。我已经研究了以下问题很长一段时间,但尚未找到原因和解决方案。在UIKit中集成视图时,会出现此问题。我试图创建一个简单的可点击视图,点击时垂直展开/折叠 这就是SwiftUI视图预览的样子(以及它应该如何工作):Ios UIKit中的可扩展SwiftUI视图垂直居中,ios,uikit,swiftui,Ios,Uikit,Swiftui,我正在将一些新的SwiftUI视图集成到UIKit应用程序中,但遇到了一个问题。我已经研究了以下问题很长一段时间,但尚未找到原因和解决方案。在UIKit中集成视图时,会出现此问题。我试图创建一个简单的可点击视图,点击时垂直展开/折叠 这就是SwiftUI视图预览的样子(以及它应该如何工作): 以下是我在UIKit中实现SwiftUI视图时得到的结果: 看起来,即使我将UIHostingController视图的顶部约束到父视图,UIHostingController视图仍然垂直居中 如评
以下是我在UIKit中实现SwiftUI视图时得到的结果:
看起来,即使我将UIHostingController视图的顶部约束到父视图,UIHostingController视图仍然垂直居中 如评论中所述,我可以将HostController视图的底部约束到其父视图的底部,但这会使下面的内容变得不可理解 我要寻找的是HostController视图约束(特别是高度)与SwiftUI视图框架匹配的解决方案 SwiftUI视图的代码:
import SwiftUI
struct ColorView: View {
@State var isCollapsed = true
var body: some View {
VStack {
VStack(spacing: 5) {
HStack {
Spacer()
Text("Title")
Spacer()
}
.frame(height: 100)
if !isCollapsed {
HStack {
Spacer()
Text("description")
Spacer()
}
.padding(40)
}
}
.background(Color(isCollapsed ? UIColor.red : UIColor.blue))
.onTapGesture {
withAnimation {
self.isCollapsed.toggle()
}
}
Spacer()
}
}
}
struct ColorView_Previews: PreviewProvider {
static var previews: some View {
return ColorView()
}
}
struct ViewControllerRepresentable: UIViewControllerRepresentable {
typealias UIViewControllerType = ViewController
func makeUIViewController(context: UIViewControllerRepresentableContext<ViewControllerRepresentable>) -> ViewControllerRepresentable.UIViewControllerType {
return ViewController()
}
func updateUIViewController(_ uiViewController: ViewControllerRepresentable.UIViewControllerType, context: UIViewControllerRepresentableContext<ViewControllerRepresentable>) { }
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let colorView = ColorView()
let colorController = UIHostingController(rootView: colorView)
addChild(colorController)
view.addSubview(colorController.view)
colorController.didMove(toParent: self)
colorController.view.translatesAutoresizingMaskIntoConstraints = false
colorController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
colorController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
colorController.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
}
}
struct ViewControllerRepresentable_Previews: PreviewProvider {
static var previews: some View {
Group {
ViewControllerRepresentable()
}
}
}
以及上述SwiftUI视图的ViewController中的UIKit实现:
import SwiftUI
struct ColorView: View {
@State var isCollapsed = true
var body: some View {
VStack {
VStack(spacing: 5) {
HStack {
Spacer()
Text("Title")
Spacer()
}
.frame(height: 100)
if !isCollapsed {
HStack {
Spacer()
Text("description")
Spacer()
}
.padding(40)
}
}
.background(Color(isCollapsed ? UIColor.red : UIColor.blue))
.onTapGesture {
withAnimation {
self.isCollapsed.toggle()
}
}
Spacer()
}
}
}
struct ColorView_Previews: PreviewProvider {
static var previews: some View {
return ColorView()
}
}
struct ViewControllerRepresentable: UIViewControllerRepresentable {
typealias UIViewControllerType = ViewController
func makeUIViewController(context: UIViewControllerRepresentableContext<ViewControllerRepresentable>) -> ViewControllerRepresentable.UIViewControllerType {
return ViewController()
}
func updateUIViewController(_ uiViewController: ViewControllerRepresentable.UIViewControllerType, context: UIViewControllerRepresentableContext<ViewControllerRepresentable>) { }
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let colorView = ColorView()
let colorController = UIHostingController(rootView: colorView)
addChild(colorController)
view.addSubview(colorController.view)
colorController.didMove(toParent: self)
colorController.view.translatesAutoresizingMaskIntoConstraints = false
colorController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
colorController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
colorController.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
}
}
struct ViewControllerRepresentable_Previews: PreviewProvider {
static var previews: some View {
Group {
ViewControllerRepresentable()
}
}
}
struct ViewControllerRepresentable:UIViewControllerRepresentable{
typealias UIViewControllerType=ViewController
func makeUIViewController(上下文:UIViewControllerRepresentableContext)->ViewControllerRepresentable.UIViewControllerType{
返回ViewController()
}
func updateUIViewController(uUIViewController:ViewControllerRepresentable.UIViewControllerType,上下文:UIViewControllerRepresentableContext){}
}
类ViewController:UIViewController{
重写func viewDidLoad(){
super.viewDidLoad()
让colorView=colorView()
让colorController=UIHostingController(根视图:colorView)
addChild(颜色控制器)
view.addSubview(colorController.view)
colorController.didMove(toParent:self)
colorController.view.translatesAutoresizingMaskIntoConstraints=false
colorController.view.leadingAnchor.constraint(等式:view.leadingAnchor).isActive=true
colorController.view.trailingAnchor.constraint(equalTo:view.trailingAnchor).isActive=true
colorController.view.topAnchor.constraint(equalTo:view.topAnchor).isActive=true
}
}
结构ViewControllerRepresentable\u预览:PreviewProvider{
静态var预览:一些视图{
团体{
ViewControllerRepresentable()
}
}
}
非常感谢您的帮助。以下是在iOS单视图游乐场(Xcode 11.2)中测试的代码快照。原始的
ColorView
没有更改,因此下面没有重复
UIKit UIViewController中集成的SwiftUI视图的行为与纯SwiftUI环境中的行为相同
import UIKit
import PlaygroundSupport
import SwiftUI
class MyViewController : UIViewController {
override func loadView() {
let view = UIView()
view.backgroundColor = .white
self.view = view
}
override func viewDidLoad() {
super.viewDidLoad()
let child = UIHostingController(rootView: ColorView())
addChild(child)
self.view.addSubview(child.view)
child.didMove(toParent: self)
child.view.translatesAutoresizingMaskIntoConstraints = false
child.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
child.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
child.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
child.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
你好谢谢你尝试一下。您的方法(将hostcontroller视图的底部约束到父视图)的问题是父视图的内容不再可交互,因为另一个视图在它前面(即使hostcontroller视图不一定与父视图具有相同的高度)。这是不同的问题)