Search code examples
iosswiftswiftuiuikituibarbuttonitem

Navigation bar button becomes smaller when using it as a UIViewRepresentable


I created a reusable share button view in SwiftUI that I added to a navigation view. Here is what that button looks like at a high level.

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)
            }
        }
    }

I centralize my navigation within a navigation router which is based on UIKit and due to some limitations highlighted in this question I had to move the whole share button implementation to a UIViewRepresentable.

That looks like this:

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) {
                
            }
        }
    }

While everything seems to work, the button looks visibly smaller with this new implementation.

Before:

UIBarButtonItem SwiftUI

After:

UIBarButtonItem SwiftUI UIView Representable

How can I get the size to be like before using my new approach ?


Solution

  • In your ShareButtonRepresentable code, create a large image config:

        let largeConfig = UIImage.SymbolConfiguration(scale: .large) // Add this line
        let largeImage = image?.applyingSymbolConfiguration(largeConfig) // And this line
        button.setImage(largeImage, for: .normal)
    

    And you will see its size should match SwiftUI's approach. (SwiftUI has the .imageScale(.large) modifier applied to it. This modifier increases the size of the image.)

    enter image description here