SwiftUI接入UIKit自定义按钮时CGAffineTransform缩放效果异常问题
问题根因
该异常由两个交互逻辑冲突导致:
- UIKit侧的缩放动画未配置
beginFromCurrentState选项,首次触发时会从视图初始布局的临时transform状态插值,而非默认的identity,出现反向放大的视觉效果 - SwiftUI会对托管的UIKit视图默认启用隐式动画,首次触发UIKit动画时和SwiftUI布局周期冲突,导致动画起始值异常
修复方案
第一步:修改UIKit侧CustomButton的动画实现
移除不必要的主队列异步调度,添加动画选项避免起始值异常:
private func rescaleButtonSize(scaleXto x: CGFloat = 1.0,scaleYto y: CGFloat = 1.0) { // 触发按钮事件的回调本身就在主线程,不需要额外调度到主队列 UIView.animate(withDuration: 0.2, delay: 0, options: [.allowUserInteraction, .beginFromCurrentState]) { self.transform = CGAffineTransform(scaleX: x, y: y) } }
第二步:优化UIViewRepresentable封装逻辑
移除makeUIView中不必要的主动调用updateUIView的代码,禁用更新时的隐式动画干扰:
import SwiftUI struct SwiftUI_CustomButton: UIViewRepresentable { var title: String var handler: (() -> Void)? = nil func makeUIView(context: Context) -> CustomButton { let button = CustomButton() button.addAction { handler?() } // 提高内容拥抱优先级,避免SwiftUI随意拉伸按钮 button.setContentHuggingPriority(.defaultHigh, for: .horizontal) button.setContentHuggingPriority(.defaultHigh, for: .vertical) return button } func updateUIView(_ button: CustomButton, context: Context) { UIView.performWithoutAnimation { button.title = title button.layoutIfNeeded() } } }
第三步:调整SwiftUI侧调用代码
添加fixedSize修饰符,让SwiftUI按照UIKit按钮的固有大小布局,避免强制拉伸导致transform异常:
struct CustomButton_SwiftUI: View { var body: some View { VStack(alignment: .leading, spacing: 8) { SwiftUI_CustomButton( title: "Actual" ) { // 按钮点击逻辑 } .fixedSize() } .padding(16) } }
内容的提问来源于stack exchange,提问作者Dreiohc
相关产品推荐
相关产品推荐

