SwiftUI NavigiationView'da varsayılan Gezinme Çubuğu alanı nasıl kaldırılır


94

SwiftUI'de yeniyim (çoğu insan gibi) ve bir Navigasyon Görünümü'ne katıştırdığım bir Listenin üstündeki bazı beyaz boşlukları nasıl kaldıracağımı bulmaya çalışıyorum

Bu resimde, Listenin üzerinde biraz beyaz boşluk olduğunu görebilirsiniz.

Şimdiki versiyonu

Başarmak istediğim şey bu

İdeal Versiyon

Kullanmayı denedim

.navigationBarHidden(true)

ancak bu gözle görülür bir değişiklik yapmadı.

Şu anda navigasyonumu ayarlıyorumBunun gibi görüntüle

 NavigationView {
                FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
                    .navigationBarHidden(true)
                }

FileBrowserView, bunun gibi tanımlanmış bir Liste ve Hücrelerin bulunduğu bir görünümdür

List {
   Section(header: Text("Root")){
    FileCell(name: "Test", fileType: "JPG",fileDesc: "Test number 1")

                    FileCell(name: "Test 2", fileType: "txt",fileDesc: "Test number 2")
                    FileCell(name: "test3", fileType: "fasta", fileDesc: "")
}
}

Buradaki nihai amacın, bir dosya ağacında daha derinlere gitmek için bu hücrelere tıklayabilmeniz ve bu nedenle daha derin gezinmede çubukta bir Geri düğmesi görüntülemeniz gerektiğine dikkat etmek isterim, ancak burada hiçbir şey istemiyorum. ilk görüşüm sırasında olduğu gibi.

Yanıtlar:


146

Nedense, SwiftUI de set gerektirir .navigationBarTitleiçin .navigationBarHiddendüzgün çalışması için.

NavigationView {
    FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
        .navigationBarTitle("")
        .navigationBarHidden(true)
}

Güncelleme

@Peacemoon Açıklamalarda belirttiği gibi, senin kadar gizli gezinti çubuğu kalıntıları bağımsız olarak ayarlanmış olup olmadığına, navigasyon yığınında derin gezinmek navigationBarHiddeniçin falsesonraki görünümlerinde. Yorumlarda da söylediğim gibi, bu ya Apple'ın zayıf uygulamasının bir sonucudur ya da sadece korkunç dokümantasyondur (kim bilir, bunu başarmanın "doğru" bir yolu olabilir).

Durum ne olursa olsun, orijinal posterin istenen sonuçlarını üretiyor gibi görünen bir geçici çözüm buldum. Bunu tavsiye etmekte tereddüt ediyorum çünkü gereksiz yere hile gibi görünüyor, ancak gezinme çubuğunu gizlemenin ve gizlemenin açık bir yolu olmadan yapabileceğimin en iyisi bu.

Bu örnek üç görünüm kullanır - View1gizli bir gezinme çubuğuna sahiptir View2ve View3her ikisinde de başlıkları olan görünür gezinme çubukları vardır.

struct View1: View {
    @State var isNavigationBarHidden: Bool = true

    var body: some View {
        NavigationView {
            ZStack {
                Color.red
                NavigationLink("View 2", destination: View2(isNavigationBarHidden: self.$isNavigationBarHidden))
            }
            .navigationBarTitle("Hidden Title")
            .navigationBarHidden(self.isNavigationBarHidden)
            .onAppear {
                self.isNavigationBarHidden = true
            }
        }
    }
}

struct View2: View {
    @Binding var isNavigationBarHidden: Bool

    var body: some View {
        ZStack {
            Color.green
            NavigationLink("View 3", destination: View3())
        }
        .navigationBarTitle("Visible Title 1")
        .onAppear {
            self.isNavigationBarHidden = false
        }
    }
}

struct View3: View {
    var body: some View {
        Color.blue
            .navigationBarTitle("Visible Title 2")
    }
}

Ayar navigationBarHiddeniçin falsenavigasyon yığınında derin görünümleri düzgün başlangıçta belirlenen görüşündedir tercihini geçersiz kılmak için görünmüyor navigationBarHiddeniçin truesadece ben bir orijinal bakış tercihini değiştirmek için bağlayıcı kullanıyordum gelebilir geçici çözümü yüzden, ne zaman yeni bir görünüm gezinme yığınına aktarılır.

Dediğim gibi, bu karmaşık bir çözüm, ancak Apple'ın resmi bir çözümü olmadan, bulabildiğim en iyisi bu.


5
Bu benim sorunumu çözdü! Gezinme çubuğunu gizlemeden önce bir başlığa sahip olmanız çok garip ...
Vapidant

5
Hata beta dışında hala orada: /
Daniel Ryan

1
@Peacemoon Bunu daha önce fark etmemiştim. Sonuç olarak, Apple'ın uygulaması burada oldukça özensiz görünüyor. Sen başlamak çubuğunu gizlemek için sadece başlık ayarlamak zorunda ve ayar olmamalıdır navigationBarHiddeniçin falsegezinme çubuğunu göstermek gereken bir sonraki görünümü, ama oldu. Sonunda SwiftUI'nin ne kadar kötü belgelendirildiğinden bıktım ve UIKit'e geri döndüm ve en az 20 kişinin buraya sadece gezinme çubuğunu nasıl gizleyeceğini öğrenmek için geldiği gerçeği, Apple'ın uygulaması ve / veya dokümantasyonu için oldukça zayıf konuşuyor. Üzgünüm senin için daha iyi bir cevabım yok.
graycampbell

2
@SambitPrakash Daha önce bir NavigationView içine bir TabView yerleştirmemiştim ve Apple, anlatabildiğim kadarıyla onları uygulamalarına bu şekilde yerleştirmiyor gibi görünüyor. Bir NavigationView içine bir TabView yerleştirmenin amaçlanıp planlanmadığı benim için hiçbir zaman tam olarak anlaşılmamıştı ve SwiftUI'nin onları bu şekilde yerleştirdiğinizde ortaya çıkan bazı garip hatalar olduğunu biliyorum. TabViews bana her zaman NavigationViews'tan daha üst düzey bir gezinme biçimi gibi hissettirdi. Bunun yerine NavigationView'ü TabView içine yerleştirirseniz, geçici çözümümün hala çalışması gerektiğine inanıyorum.
graycampbell

2
@kar Bu cevabın hala dikkat çekmesi ve olumlu oylar alması hayal kırıklığı yaratıyor. Bunu, geçici bir hatanın olması gereken geçici bir çözüm olarak yazdım. Son zamanlarda test etmedim, ancak açıkçası onunla ilgili birçok sorun var. Birkaç kişi de NavigationView kullanmadan görünümler arasında gezinip gezinemeyeceğinizi sordu. Cevap evet, ancak aslında kendi NavigationView'unuzu sıfırdan yazmanız gerekir. Görünümler arasında sihirli bir şekilde gezinemezsiniz. Bir şey bu görünümleri yönetmeli ve aralarında geçişler sağlamalı, bu yüzden NavigationView'a sahibiz.
graycampbell

18

Bir NavigationView , gezinme çubuğunu görünümünüzün üstüne eklemektir. İOS'ta 2 tür gezinme çubuğu vardır: büyük ve standart.

görüntü açıklamasını buraya girin

Gezinme çubuğu istemiyorsanız:

FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))

Büyük bir gezinme çubuğu istiyorsanız (genellikle üst düzey görünümleriniz için kullanılır):

NavigationView {
    FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
    .navigationBarTitle(Text("Title"))
}

Standart (satır içi) bir gezinme çubuğu istiyorsanız (genellikle alt düzey görünümler için kullanılır):

NavigationView {
    FileBrowserView(jsonFromCall: URLRetrieve(URLtoFetch: applicationDelegate.apiURL))
    .navigationBarTitle(Text("Title"), displayMode: .inline)
}

Umarım bu cevap size yardımcı olur.

Daha fazla bilgi: Apple Belgeleri


29
Navigasyon çubuğunu gizlemek isteyebileceğiniz ve aynı zamanda bir NavigationView. A'nın amacı NavigationViewyalnızca bir gezinme çubuğunu görüntülemek değildir.
graycampbell

6
Yığın içinde gezinme ve görünümlerden kolayca geri dönebilme işlevselliği için NavigiationView olmasını istiyorum, ilk görünümde bir navigiationBar'a ihtiyacım yok.
Vapidant

2
NavigationView olmadan görünümler arasında gezinmenin bir yolu var mı?
user1445685

Temelde. Hayır. En azından henüz swiftui'de değil
Gustavo Parrado

Bu yanıt, bir NavigationView'e sahip olmak, başka bir görünüme gitmek için gerekli olduğundan orijinal soruda etkili olduğu için yararlı değildir.
JaseTheAce

16

Görünüm Değiştiricileri kolaylaştırdı:

//ViewModifiers.swift

struct HiddenNavigationBar: ViewModifier {
    func body(content: Content) -> some View {
        content
        .navigationBarTitle("", displayMode: .inline)
        .navigationBarHidden(true)
    }
}

extension View {
    func hiddenNavigationBarStyle() -> some View {
        modifier( HiddenNavigationBar() )
    }
}

Misal: görüntü açıklamasını buraya girin

import SwiftUI

struct MyView: View {
    var body: some View {
        NavigationView {
            VStack {
                Spacer()
                HStack {  
                    Spacer()
                    Text("Hello World!")
                    Spacer()
                }
                Spacer()
            }
            .padding()
            .background(Color.green)
            //remove the default Navigation Bar space:
            .hiddenNavigationBarStyle()
        }
    }
}

4
İtilen bir görünüm denetleyicisi için sorunu çözmez.
damjandd

Burada, değiştiricinin NavigationView'e değil, görünümün hemen içine eklenmesi önemli görünüyor. Bu, işe yaraması için tüm farkı yarattı. Teşekkürler! :-)
JaseTheAce

10

Başlığı, üzerindeki alanı kaldırmak istediğiniz Görünüm için satır içi olarak ayarlarsanız, bunun bir NavigationView içeren bir görünümde yapılması gerekmez, bunun yerine navigasyon da yapılır.

.navigationBarTitle("", displayMode: .inline)

Başlangıç ​​sorunu çözüm 1 sonra sadece Gezinme çubuklarının görünümünü değiştirin

init() {
    UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
    UINavigationBar.appearance().shadowImage = UIImage()
}

ilk NavigationView öğesini tutan görünümde. son çözüm

Görünümü ekrandan ekrana değiştirmek istiyorsanız, uygun görünümlerdeki görünümü değiştirin


1
Bu çözüm kullanışlıdır
Murilo Medeiros

9

Ayrıca bu sayfada bahsedilen tüm çözümleri denedim ve sadece @graycampbell çözümünü iyi çalışan animasyonlarla iyi çalışan bir çözüm buldum. Bu yüzden, hackingwithswift.com örneğiyle, her yerden erişebileceğim, uygulama boyunca kullanabileceğim bir değer yaratmaya çalıştım.

Bir ObservableObjectsınıf oluşturdum

class NavBarPreferences: ObservableObject {
    @Published var navBarIsHidden = true
}

Ve SceneDelegatebenzer şekilde ilk görünüme aktarın

var navBarPreferences = NavBarPreferences()
window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(navBarPreferences))

Ardından ContentView, bu Gözlemlenebilir nesneyi bu şekilde takip edebilir ve aşağıdakilere bir bağlantı oluşturabiliriz SomeView:

struct ContentView: View {
    //This variable listens to the ObservableObject class
    @EnvironmentObject var navBarPrefs: NavBarPreferences

    var body: some View {
        NavigationView {
                NavigationLink (
                destination: SomeView()) {
                    VStack{
                        Text("Hello first screen")
                            .multilineTextAlignment(.center)
                            .accentColor(.black)
                    }
                }
                .navigationBarTitle(Text(""),displayMode: .inline)
                .navigationBarHidden(navBarPrefs.navBarIsHidden)
                .onAppear{
                    self.navBarPrefs.navBarIsHidden = true
            }
        }
    }
}

Ve sonra ikinci görünüme (SomeView) erişirken, bunu şu şekilde tekrar gizleriz:

struct SomeView: View {
    @EnvironmentObject var navBarPrefs: NavBarPreferences

    var body: some View {
        Text("Hello second screen")
        .onAppear {
            self.navBarPrefs.navBarIsHidden = false
        }
    } 
}

Önizlemelerin çalışmasını sağlamak için önizlemeye NavBar Tercihlerini şu şekilde ekleyin:

struct SomeView_Previews: PreviewProvider {
    static var previews: some View {
        SomeView().environmentObject(NavBarPreferences())
    }
}

2
kullanarak @EnvironmentObject ziyade Uygulamanın tamamında veri aktarmak için çok daha iyi olduğunu @State seni daha cevap tercih böylece,
Arafin Russell

7

Bu, SwiftUI'de bulunan bir hatadır ( hala Xcode 11.2.1'den itibaren ). Bunu ViewModifierdüzeltmek için mevcut yanıtlardan alınan koda göre bir yazdım :

public struct NavigationBarHider: ViewModifier {
    @State var isHidden: Bool = false

    public func body(content: Content) -> some View {
        content
            .navigationBarTitle("")
            .navigationBarHidden(isHidden)
            .onAppear { self.isHidden = true }
    }
}

extension View {
    public func hideNavigationBar() -> some View {
        modifier(NavigationBarHider())
    }
}

2
Bununla, "arka arkaya hızlı" hareketi artık çalışmıyor
Urkman

6

Yerel Görünüm protokolünü şu şekilde genişletebilirsiniz :

extension View {
    func hideNavigationBar() -> some View {
        self
            .navigationBarTitle("", displayMode: .inline)
            .navigationBarHidden(true)
    }
}

Sonra örneğin arayın:

ZStack {
    *YOUR CONTENT*
}
.hideNavigationBar()

5

Benim için, ben uygulayarak edildi .navigationBarTitleiçin NavigationViewdeğil için Listsuçlu oldu. Bu benim için Xcode 11.2.1'de çalışıyor:

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: DetailView()) {
                    Text("I'm a cell")
                }
            }.navigationBarTitle("Title", displayMode: .inline)
        }
    }
}

Üstte boşluk olmayan gezinme çubuğu ve liste


5
Sorulan soru ilgisiz
Ahmed Sahib

3
@AhmedSahib Soru, "SwiftUI NavigiationView'da varsayılan Gezinme Çubuğu alanı nasıl kaldırılır" idi ve benim kodum bunu başarıyor.
Genki

1
Mükemmel tavsiye. Çözümüm için, boşluktan kurtulmak için iç listeye iki değiştirici uygulamak zorunda kaldım: .navigationBarTitle ("", displayMode: .automatic) .navigationBarHidden (true) Sonra, dış NavigationView'e uygulamam gerekiyordu: .navigationBarTitle (" TITLE ", displayMode: .inline)
Frankenstein

4

Benim için bunun nedeni, NavigationView'umu mevcut bir. Aslında birinin diğerinin içinde olması. Bir NavigationView'dan geliyorsanız, zaten bir NavigatonView'da olduğunuz için bir sonrakinin içinde bir tane oluşturmanıza gerek yoktur.


2

@Graycampbell'in cevabına benzer, ancak biraz daha basit:

struct YourView: View {

    @State private var isNavigationBarHidden = true

    var body: some View {
        NavigationView {
            VStack {
                Text("This is the master view")
                NavigationLink("Details", destination: Text("These are the details"))
            }
                .navigationBarHidden(isNavigationBarHidden)
                .navigationBarTitle("Master")
                .onAppear {
                    self.isNavigationBarHidden = true
                }
                .onDisappear {
                    self.isNavigationBarHidden = false
                }
        }
    }
}

Gittiğiniz görünümlerde geri düğmesinin yanında gösterildiğinden başlığın ayarlanması gereklidir.


2

SwiftUI 2

Gezinme çubuğunun daha az yer kaplamasını sağlamak için özel bir değiştirici vardır:

.navigationBarTitleDisplayMode(.inline)

Artık gezinme çubuğunu gizlemenize veya başlığını ayarlamanıza gerek yok.


0

@Vatsal Manot'un bunun için bir değiştirici oluşturmak için verdiği fikir gerçekten çok hoşuma gitti .
Çıkarma isHiddenBen değiştirici isim kendisi kadar yararlı bulmuyorum, onun cevabını malını o gizlemek gezinti çubuğu gösteriyor.

// Hide navigation bar.
public struct NavigationBarHider: ViewModifier {

    public func body(content: Content) -> some View {
        content
            .navigationBarTitle("")
            .navigationBarHidden(true)
    }
}

extension View {
    public func hideNavigationBar() -> some View {
        modifier(NavigationBarHider())
    }
}

0

Kullanıcı oturum açtıktan sonra bir TabView görüntülenmesi gereken bir uygulama üzerinde çalışırken benzer bir sorun yaşadım.

@Graycampbell'in yorumunda önerdiği gibi, bir TabView bir NavigationView içine yerleştirilmemelidir, aksi takdirde kullanılırken bile "boş alan" görünecektir .navigationBarHidden(true)

ZStackNavigationView’u gizlemek için a kullandım . Bu basit örnek için, UI görünürlüğünü kullanıyorum @Stateve @Bindingyönetiyorum, ancak ortam nesnesi gibi daha karmaşık bir şey kullanmak isteyebilirsiniz.

struct ContentView: View {

    @State var isHidden = false

    var body: some View {
        
        ZStack {
            if isHidden {
                DetailView(isHidden: self.$isHidden)
            } else {
                NavigationView {
                    Button("Log in"){
                        self.isHidden.toggle()
                    }
                    .navigationBarTitle("Login Page")
                }
            }
        }
    }
}

Log In butonuna bastığımızda ilk sayfa kaybolur ve DetailView yüklenir. Oturumu Kapat düğmesini değiştirdiğimizde Oturum Açma Sayfası yeniden görünüyor

struct DetailView: View {
    
    @Binding var isHidden: Bool
    
    var body: some View {
        TabView{
            NavigationView {
                Button("Log out"){
                    self.isHidden.toggle()
                }
                .navigationBarTitle("Home")
            }
            .tabItem {
                Image(systemName: "star")
                Text("One")
            }
        }
    }
}

0

Bu problem için benim çözümüm @ Genki ve @Frankenstein tarafından önerilen ile aynıydı.

Aralıklardan kurtulmak için iç listeye (NavigationView DEĞİL) iki değiştirici uyguladım:

.navigationBarTitle("", displayMode: .automatic)
.navigationBarHidden(true) 

Dış NavigationView'da, ardından .navigationBarTitle("TITLE")başlığı ayarlamak için uygulanır .


1
Hiçbir şey yapmaz.
TruMan1

-8

Koyarak deneyin NavigationViewiçeride a GeometryReader.

GeometryReader {
    NavigationView {
        Text("Hello World!")
    }
}

NavigationViewKök görünüm olduğunda garip davranışlar yaşadım .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.