SwiftUI DragGesture通过UIHostingController嵌入UIKit后仅能拖动一次如何解决
问题原因
你给UIHostingController的view仅设置了左、顶约束,没有设置宽高约束,它的尺寸会默认匹配初始状态下MovingCircle的内容大小,也就是20x20的固定尺寸,且位置固定在左100、顶100的坐标。当你拖拽圆形改变offset后,圆形视觉上移出了宿主view的20x20区域,但是宿主view本身的frame没有任何变化,后续点击已经偏移的圆形时,点击位置不在宿主view的响应范围内,自然就触发不了手势。
解决方案(完全保留原有SwiftUI拖拽逻辑)
第一步:修改SwiftUI代码,扩大触控响应区域
给圆形套一层全屏透明的根容器,既不影响视觉效果,又能让整个宿主区域都可以响应手势:
struct MovingCircle: View { @State private var dragged = CGSize.zero @State private var accumulated = CGSize.zero var body: some View { // 透明根视图撑满整个宿主容器,扩大响应范围 Color.clear .frame(maxWidth: .infinity, maxHeight: .infinity) .overlay( Circle() .frame(width: 20, height: 20) .border(Color.red) .offset(x: self.dragged.width, y: self.dragged.height) .gesture(DragGesture() .onChanged{ value in self.dragged = CGSize(width: value.translation.width + self.accumulated.width, height: value.translation.height + self.accumulated.height) } .onEnded{ value in self.dragged = CGSize(width: value.translation.width + self.accumulated.width, height: value.translation.height + self.accumulated.height) self.accumulated = self.dragged } ) ) } }
第二步:修改UIKit侧约束,让宿主view匹配父视图尺寸
把原本仅设置左、顶约束的逻辑,替换为让UIHostingController的view撑满父视图:
let swiftUIView = UIHostingController(rootView: MovingCircle()) swiftUIView.view.translatesAutoresizingMaskIntoConstraints = false addChild(swiftUIView) view.addSubview(swiftUIView.view) swiftUIView.didMove(toParent: self) // 约束宿主view和父视图完全对齐 NSLayoutConstraint.activate([ swiftUIView.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), swiftUIView.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), swiftUIView.view.topAnchor.constraint(equalTo: view.topAnchor), swiftUIView.view.bottomAnchor.constraint(equalTo: view.bottomAnchor) ])
如果你不需要宿主view撑满全屏,也可以给它设置固定的宽高(比如300x300),只要保证圆形的拖拽范围不会超出这个固定区域即可正常响应手势。
内容的提问来源于stack exchange,提问作者Kiran Jasvanee
相关产品推荐
相关产品推荐

