You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 22:09:50