Как разместить логотип в NavigationView в swiftui?

Я пытаюсь использовать изображение логотипа вместо заголовка NavigationView в верхней части приложения. Не удалось найти документацию по использованию изображений в навигационном представлении.

8 ответов

SwiftUI 2

В SwiftUI 2 / iOS 14 вы можете создать ToolbarItem с principal размещение:

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

Увидеть ToolbarItemPlacementдокументация для большего количества мест размещения.

NavigationView.navigationBarTitle() можно только взять Text() спор прямо сейчас. Вы могли бы вместо этого использовать .navigationBarItems() установить Image как либо trailing или же leading аргумент, но это эквивалент SwiftUI UINavigationItem.leftBarButtonItem[s] а также UINavigationItem.rightBarButtonItem[s], что означает, что вы ограничены размерами кнопок панели навигации. Но если вы согласны с этим, вы можете установить пустой заголовок, чтобы вы могли указать панель навигации стандартной высоты.

Жесткое позиционирование

Если вы можете жить с самим собой, вы можете подделать центрированный элемент панели навигации, жестко закодировав отступ вокруг изображения, например:

.padding(.trailing, 125),

(Обратите внимание, что я намеренно расположил его не по центру, чтобы вы могли видеть, что он жестко запрограммирован.)

Немного меньше жестко позиционированного позиционирования

Еще лучше было бы обернуть все это в GeometryReader { geometry in ... } блок, чтобы использовать размеры экрана для расчета точного позиционирования, если вы знаете точную ширину используемого вами изображения:

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

Если вы не хотите его взломать, вот что вы можете сделать:

Стандартная высота навигационной панели, левая кнопка

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

Стандартная высота навигационной панели, правая кнопка

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

Увеличенная высота панели навигации, без заголовка, левая кнопка

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

Пользователь это:

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

Кредит: https://sarunw.com/posts/custom-navigation-bar-title-view-in-swiftui/

С SwiftUIX вы можете использоватьnavigationBarTitleView(View):

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

Я не хочу требовать 100% точности, если изображение заголовка расположено по центру, но визуально оно мне кажется центральным. Делайте свое суждение и отрегулируйте отступы:)

Вот код:

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

Чтобы расширить ответ NRitH, размещение вашего логотипа в другом компоненте (если использовать способ выражения React) может помочь любому, кто хочет понять концепции.

Фактическое изображение может быть заключено в любое представление контейнера, такое как VStack и т. Д. Примером настройки структуры как компонента, который будет использоваться в наших элементах навигации, может быть что-то вроде следующего:

struct NavLogo: View {

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

Если задано соотношение сторон, необходимо установить только ширину кадра в представлении контейнера. Мы также могли бы установить свойство в NavLogo, чтобы установить ширину и / или высоту из внедрения зависимости свойств. Тем не менее, наш navigationBarItems становится более простым и читаемым.

NavigationView {
    Text("Home View")
        .navigationBarItems(
            leading: NavLogo()
            trailing: ProfileButton()
        )
    }

В iOS 13 есть небольшой хитрый способ добиться этого:

      private var logo: some View {
    Image("logo-image")
}

var body: some View {
    GeometryReader { g in
        content()
            .navigationBarTitle("")
            .navigationBarItems(leading:
                                    ZStack(alignment: .leading) {
                                        logo.frame(width: g.size.width).padding(.trailing, 8)
                                        HStack {
                                            leadingItems().padding(.leading, 10)
                                            Spacer()
                                            trailingItems().padding(.trailing, 10)
                                        }
                                        .frame(width: g.size.width)
                                    }
                                )
    }
}

Попробуйте следующее.

struct ContainerView: View {
    var body: some View {
        VStack {
            Image(systemName: "person.crop.square")
            ContentView()
        }
    }
}

У меня это сработало.

Убедитесь, что вы изменили ContentView на ContainerView внутри SceneDelegate.swift перед запуском на симуляторе или устройстве.

Другие вопросы по тегам