Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to put a logo in NavigationView in SwiftUI?

Tags:

ios

swiftui

I am trying to use a logo image instead of a NavigationView title at the top section of the app. Couldn't find any documentation of using images inside a NavigationView.

like image 372
Baisampayan Saha Avatar asked Jun 11 '19 14:06

Baisampayan Saha


People also ask

How do I customize my navigation bar in SwiftUI?

To customize a navigation bar title view in SwiftUI, we simply set ToolbarItem of placement type . principal to a new . toolbar modifier.

What is a NavigationView in SwiftUI?

NavigationView is one of the most important components of a SwiftUI app, allowing us to push and pop screens with ease, presenting information in a clear, hierarchical way for users.


6 Answers

iOS 14+

Starting from iOS 14 you can create a ToolbarItem with the principal placement:

struct ContentView: View {
    var body: some View {
        NavigationView {
            Text("Test")
                .toolbar {
                    ToolbarItem(placement: .principal) {
                        Image(systemName: "ellipsis.circle")
                    }
                }
        }
    }
}

See the ToolbarItemPlacement documentation for more placements.

like image 138
pawello2222 Avatar answered Oct 18 '22 03:10

pawello2222


NavigationView.navigationBarTitle() can only take a Text() argument right now. You could instead use .navigationBarItems() to set an Image as either the trailing or leading argument, but this is the SwiftUI equivalent of UINavigationItem.leftBarButtonItem[s] and UINavigationItem.rightBarButtonItem[s], which means that you're restricted to navigation bar button dimensions. But if you're ok with that, you may want to set a blank title so that you can specify a standard-height navigation bar.

Hard-Coded Positioning

If you can stand to live with yourself, you can fake a centered nav bar item by hard-coding padding around the image, like

.padding(.trailing, 125),

enter image description here

(Note that I deliberately positioned it off-center so that you can see that it's hard-coded.)

Slightly Less Hard-Coded Positioning

Even better would be to wrap the whole thing in a GeometryReader { geometry in ... } block to use the screen dimensions to calculate precise positioning, if you know the exact width of the image you're using:

GeometryReader { geometry in
    NavigationView {
        ...
    }
        .navigationBarTitle(Text(""), displayMode: .inline)
        .navigationBarItems(trailing:
            PresentationButton(
                Image(systemName: "person.crop.circle")
                    .imageScale(.large)
                    .padding(.trailing, (geometry.size.width / 2.0) + -30), // image width = 60
                destination: ProfileHost()
            )
        )

enter image description here

If you don't want to hack it, here's what you can do:

Standard nav bar height, left button item

.navigationBarTitle(Text(""), displayMode: .inline)
.navigationBarItems(leading:
    PresentationButton(
        Image(systemName: "person.crop.circle")
            .imageScale(.large)
            .padding(),
        destination: ProfileHost()
    )
)

enter image description here

Standard nav bar height, right button item

.navigationBarTitle(Text(""), displayMode: .inline)
.navigationBarItems(trailing:
    PresentationButton(
        Image(systemName: "person.crop.circle")
            .imageScale(.large)
            .padding(),
        destination: ProfileHost()
    )
)

enter image description here

Expanded nav bar height, no title, left button item

.navigationBarItems(leading:
    PresentationButton(
        Image(systemName: "person.crop.circle")
            .imageScale(.large)
            .padding(),
        destination: ProfileHost()
    )
)

enter image description here

like image 28
NRitH Avatar answered Oct 18 '22 01:10

NRitH


Use this:

NavigationView {
    Text("Hello, SwiftUI!")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .principal) {
                HStack {
                    Image(systemName: "sun.min.fill")
                    Text("Title").font(.headline)
                }
            }
        }
}

Credit: https://sarunw.com/posts/custom-navigation-bar-title-view-in-swiftui/

like image 45
Nilesh Avatar answered Oct 18 '22 02:10

Nilesh


With SwiftUIX, you can use navigationBarTitleView(View):

NavigationView() {
    NavigationLink(destination:YourView().navigationBarTitleView(Image(systemName: "message.fill")))
}

enter image description here

like image 22
Zorayr Avatar answered Oct 18 '22 03:10

Zorayr


I don't want to claim 100% accuracy whether title image positioned at center but visually it looks center to me. Do your judgment and adjust padding :)

enter image description here

Here is code:

            .navigationBarTitle(
            Text("")
            , displayMode: .inline)
            .navigationBarItems(leading:
                HStack {
                    Button(action: {
                    }) {
                        Image(systemName: "arrow.left")
                    }.foregroundColor(Color.oceanWhite)
                    Image("oceanview-logo")
                        .resizable()
                        .foregroundColor(.white)
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 60, height: 40, alignment: .center)
                    .padding(UIScreen.main.bounds.size.width/4+30)
                }
                ,trailing:

                HStack {

                    Button(action: {
                    }) {
                        Image(systemName: "magnifyingglass")
                        }.foregroundColor(Color.oceanWhite)
                }
        )
like image 27
Naren Avatar answered Oct 18 '22 03:10

Naren


To extend on NRitH's answer, putting your logo in a different component (to borrow a React way of putting it) may help anyone looking to understand the concepts.

The actual Image can be wrapped in any container view such as a VStack, etc. An example of setting up a struct as a component to be used in our navigation items could be something like the following:

struct NavLogo: View {

    var body: some View {
            VStack {
                Image("app-logo")
                    .resizable()
                    .aspectRatio(2, contentMode: .fit)
                    .imageScale(.large)
            }
            .frame(width: 200)
            .background(Color.clear)
    }
}

When the aspect ratio is set, only the width needs to be set on the frame on the container view. We could also set a property in the NavLogo to set width and/or height from property dependency injection. Regardless, our navigationBarItems becomes very straight forward and more readable 🙂

NavigationView {
    Text("Home View")
        .navigationBarItems(
            leading: NavLogo()
            trailing: ProfileButton()
        )
    }
like image 38
PostCodeism Avatar answered Oct 18 '22 03:10

PostCodeism