使用UIViewRepresentable后导航栏按钮尺寸缩小的解决方法
修复SwiftUI导航栏分享按钮重构后尺寸缩小问题
问题描述
我在SwiftUI中实现了一个可复用的导航栏分享按钮,原本显示正常。但因iPad上UIActivityViewController的位置问题,改用UIViewRepresentable重构后,按钮尺寸明显缩小。现有新旧实现代码如下:
原有实现代码
struct ShareButton: View { let url: URL? var body: some View { shareButton } @ViewBuilder private var shareButton: some View { if let url { Button { navigationRouter.presentActivityViewController(activityItems: [url], applicationActivities: []) } label: { Image(systemName: Constants.Image.shareIcon) } } } }
重构后代码
private struct ShareButtonRepresentable: UIViewRepresentable { let url: URL let imageSystemName: String let tintColor: UIColor let navigationRouter: NavigationRouter? let action: (() -> Void)? func makeUIView(context: Context) -> UIButton { let button = UIButton() let image = UIImage(systemName: imageSystemName) button.setImage(image, for: .normal) button.tintColor = tintColor let uiAction = UIAction() { _ in navigationRouter?.presentActivityViewController(activityItems: [url], applicationActivities: [], source: button) action?() } button.addAction(uiAction, for: .touchUpInside) return button } func updateUIView(_ uiView: UIButton, context: Context) { } } struct ShareButton: View { let url: URL? var body: some View { shareButton } @ViewBuilder private var shareButton: some View { if let url { ShareButtonRepresentable(url: url, imageSystemName: Constants.Image.shareIcon, tintColor: Constants.TintColor, navigationRouter: navigationRouter) { } } } }
解决方案
SwiftUI原生Button在导航栏中会自动应用系统默认的布局规则(比如44x44的点击区域和内边距),而通过UIViewRepresentable创建的UIButton默认没有这些约束,因此需要手动配置来匹配原有尺寸,以下是两种可行方案:
方案一:给UIButton添加内容边距
在ShareButtonRepresentable的makeUIView方法中,为按钮设置内容边距,同时建议使用.system类型的按钮以贴合系统样式:
func makeUIView(context: Context) -> UIButton { // 使用系统类型按钮,匹配原生样式 let button = UIButton(type: .system) let image = UIImage(systemName: imageSystemName) button.setImage(image, for: .normal) button.tintColor = tintColor // 添加内容边距,模拟SwiftUI Button的默认内边距 button.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) let uiAction = UIAction() { _ in navigationRouter?.presentActivityViewController(activityItems: [url], applicationActivities: [], source: button) action?() } button.addAction(uiAction, for: .touchUpInside) return button }
方案二:在SwiftUI层面设置固定尺寸
在使用ShareButtonRepresentable时,直接添加frame约束,设置导航栏按钮的标准尺寸(44x44):
ShareButtonRepresentable(url: url, imageSystemName: Constants.Image.shareIcon, tintColor: Constants.TintColor, navigationRouter: navigationRouter) { } .frame(width: 44, height: 44) // 导航栏按钮标准点击区域尺寸
内容的提问来源于stack exchange,提问作者Shawn Frank
相关产品推荐
相关产品推荐

