SwiftUI NavigiationView में डिफ़ॉल्ट नेविगेशन बार स्थान को कैसे हटाएं


94

मैं स्विफ्टयूआई (ज्यादातर लोगों की तरह) के लिए नया हूं और यह पता लगाने की कोशिश कर रहा हूं कि कैसे एक व्हाट्सएप को लिस्ट से ऊपर हटा दूं जिसे मैंने नेविगेशन व्यू में एम्बेड किया है

इस छवि में, आप देख सकते हैं कि सूची के ऊपर कुछ सफेद स्थान है

वर्तमान संस्करण

जो मैं पूरा करना चाहता हूं वह यह है

आदर्श संस्करण

मैंने प्रयोग करने की कोशिश की है

.navigationBarHidden(true)

लेकिन इसने कोई उल्लेखनीय परिवर्तन नहीं किया।

मैं वर्तमान में इस तरह से अपने navigiationView की स्थापना कर रहा हूँ

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

जहां FileBrowserView इस तरह परिभाषित एक सूची और कोशिकाओं के साथ एक दृश्य है

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

मैं यह नोट करना चाहता हूं कि यहां अंतिम लक्ष्य यह है कि आप इन कक्षों पर क्लिक करके एक फ़ाइल ट्री में गहराई से नेविगेट करने में सक्षम होंगे और इस तरह गहरे नेविगेशन पर बार पर बैक बटन प्रदर्शित करना चाहिए, लेकिन मुझे कुछ भी नहीं चाहिए शीर्ष के रूप में मेरे प्रारंभिक दृश्य के दौरान।

जवाबों:


146

किसी कारण से, SwiftUI के लिए आवश्यक है कि आप ठीक से काम करने के .navigationBarTitleलिए भी निर्धारित करें .navigationBarHidden

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

अपडेट करें

के रूप में @Peacemoon टिप्पणी में कहा, नेविगेशन पट्टी आप के रूप में छिपा रहता है नेविगेशन ढेर में गहरी नेविगेट, तो आप सेट किया जाए या नहीं की परवाह किए बिना navigationBarHiddenकरने के लिए falseबाद में विचारों में। जैसा कि मैंने टिप्पणियों में कहा है, यह या तो Apple के हिस्से पर खराब क्रियान्वयन का परिणाम है या सिर्फ भयानक दस्तावेज है (जो जानता है, शायद इसे पूरा करने का एक "सही" तरीका है)।

जो भी हो, मैं एक ऐसे वर्कअराउंड के साथ आया जो लगता है कि मूल पोस्टर के वांछित परिणाम उत्पन्न करता है। मैं इसकी सिफारिश करने में संकोच कर रहा हूं क्योंकि यह अनावश्यक रूप से हैक करने वाला लगता है, लेकिन नेविगेशन बार को छुपाने और अनसुना करने के किसी भी सीधे तरीके के बिना, यह सबसे अच्छा है जो मैं कर सकता था।

यह उदाहरण तीन विचारों का उपयोग करता है - View1एक छिपी हुई नेविगेशन पट्टी है, View2और View3दोनों में शीर्षक के साथ दृश्यमान बार हैं।

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

नेविगेशन स्टैक में गहराई navigationBarHiddenसे देखने falseपर सेट करने से दृश्य की वरीयता ठीक से ओवरराइड नहीं होती है, जो मूल रूप से सेट navigationBarHiddenहोती है true, इसलिए केवल एक नया समाधान जो मैं आ सकता था, मूल दृश्य की प्राथमिकता को बदलने के लिए एक बाध्यकारी का उपयोग कर रहा था जब एक नया दृश्य नेविगेशन स्टैक पर धकेल दिया जाता है।

जैसा मैंने कहा, यह एक हैकी समाधान है, लेकिन Apple के आधिकारिक समाधान के बिना, यह सबसे अच्छा है जो मैं साथ आने में सक्षम हूं।


5
यह मेरा मुद्दा तय हो गया! यह बहुत अजीब है कि आपके पास नेविगेशन बार छिपाने से पहले एक शीर्षक होना चाहिए ...
वापींत

5
बग अभी भी बीटा के बाहर है: /
डैनियल रयान

1
@Psymoon मैंने पहले ऐसा नहीं देखा था। सब के सब, ऐसा लगता है कि Apple से कार्यान्वयन यहाँ बहुत मैला है। आपको शीर्षक को शुरू करने के लिए बार को छिपाने के लिए सेट नहीं करना चाहिए, और अगले दृश्य पर सेटिंग navigationBarHiddenको falseनेविगेशन बार को अनहाइड करना चाहिए, लेकिन यह नहीं करता है। मैं आखिरकार तंग आ गया कि स्विफ्टयूआई ने कितना खराब दस्तावेज तैयार किया और यूआईकिट वापस चला गया, और यह तथ्य कि कम से कम 20 लोग यहां आए थे कि कैसे जानें कि नेविगेशन बार को कैसे छिपाना है, जो एप्पल के कार्यान्वयन और / या प्रलेखन के लिए बहुत खराब बोलता है। क्षमा करें, मेरे पास आपके लिए बेहतर उत्तर नहीं है।
ग्रेकैंपबेल

2
@SambitPrakash मैंने पहले कभी भी एक नेविगेशन दृश्य के अंदर एक टैब दृश्य का नामकरण नहीं किया है, और Apple उन्हें अपने एप्लिकेशन में उस तरह से घोंसला नहीं बनाता है, जहां तक ​​मैं बता सकता हूं। यह मेरे लिए कभी भी पूरी तरह से स्पष्ट नहीं है अगर किसी नेवीगेशन व्यू के अंदर एक टैब व्यू को घोंसला बनाने का इरादा है, और मुझे पता है कि स्विफ्टयूआई में कुछ अजीब कीड़े हैं जो आपको उस तरह से घोंसला बनाते हैं। TabViews ने हमेशा मुझे नेविगेशनवीक्स की तुलना में उच्च स्तर के नेविगेशन के रूप में महसूस किया है। यदि आप इसके बजाय TabView के अंदर नेविगेशन दृश्य को घोंसला बनाते हैं, तो मेरा मानना ​​है कि मेरे वर्कअराउंड को अभी भी काम करना चाहिए।
ग्रेकैम्पबेल

2
@kar यह निराशाजनक है कि इस उत्तर पर अभी भी ध्यान और उत्थान हो रहा है। मैंने इसे एक अस्थायी समाधान के रूप में लिखा था जो एक अस्थायी बग होना चाहिए था। मैंने हाल ही में इसका परीक्षण नहीं किया है, लेकिन जाहिर है कि इसके साथ बहुत सारी समस्याएं हैं। कई लोगों ने यह भी पूछा है कि क्या आप किसी नेविगेशन व्यू का उपयोग किए बिना विचारों के बीच नेविगेट कर सकते हैं। इसका उत्तर हां है, लेकिन आपको अनिवार्य रूप से अपने खुद के नेविगेशन व्यू को स्क्रैच से लिखना होगा। आप केवल जादुई रूप से विचारों के बीच नेविगेट नहीं कर सकते। कुछ को उन विचारों को प्रबंधित करना है और उनके बीच संक्रमण प्रदान करना है यही कारण है कि हमारे पास नेविगेशन व्यू है।
ग्रेस्कैंपबेल

18

एक NavigationViewका उद्देश्य आपके दृश्य के शीर्ष पर नेविगेशन बार जोड़ना है। आईओएस में, 2 प्रकार के नेविगेशन बार हैं: बड़े और मानक।

यहां छवि विवरण दर्ज करें

यदि आप नो नेविगेशन बार चाहते हैं:

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

यदि आप एक बड़ा नेविगेशन बार चाहते हैं (आमतौर पर आपके शीर्ष-स्तरीय विचारों के लिए उपयोग किया जाता है):

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

यदि आप एक मानक (इनलाइन) नेविगेशन बार (आमतौर पर उप-स्तरीय विचारों के लिए उपयोग किया जाता है) चाहते हैं:

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

आशा है कि यह उत्तर आपकी सहायता करेगा।

अधिक जानकारी: Apple प्रलेखन


29
कारण है कि आप नेविगेशन बार को छिपाना चाहते हैं जबकि ए की कार्यक्षमता को भी बनाए रख सकते हैं NavigationView। A का उद्देश्य NavigationViewकेवल नेविगेशन बार प्रदर्शित करने के लिए नहीं है।
ग्रेकैम्पबेल

6
मैं चाहता हूं कि स्टैक में नेविगेट करने की कार्यक्षमता के लिए NavigiationView और आसानी से विचारों से वापस जाने की क्षमता हो, मुझे शुरुआती दृश्य पर एक navigiationBar की आवश्यकता नहीं है।
वापीदंत

2
वहाँ नेविगेशन के बिना विचारों के माध्यम से नेविगेट करने का एक तरीका है?
user1445685

मूल रूप से। नहीं अभी तक स्विफ्टुई पर कम से कम नहीं
गुस्तावो परादो

यह उत्तर उपयोगी नहीं है क्योंकि किसी अन्य दृश्य में नेविगेट करने के लिए आवश्यक है कि मूल दृश्य में एक नेविगेशन दृश्य प्रभाव है।
जसइअनस

16

देखें संशोधक ने इसे आसान बना दिया:

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

उदाहरण: यहां छवि विवरण दर्ज करें

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
एक धक्का दृश्य नियंत्रक के लिए समस्या को ठीक नहीं करता है।
दमजंद

यहां यह महत्वपूर्ण है कि संशोधक को नेविगेशन दृश्य में नहीं जोड़ा गया है, लेकिन दृश्य सिर्फ अंदर है। यह काम करने के लिए हो रही सभी अंतर बना दिया। धन्यवाद! :-)
१२:०

10

यदि आप शीर्षक को उस दृश्य के लिए इनलाइन के रूप में सेट करते हैं जिसे आप चाहते हैं कि आप उस स्थान को हटा दें, तो इसके लिए किसी नेविगेशन दृश्य के साथ देखने की आवश्यकता नहीं है, लेकिन एक भी नेविगेट किया गया है।

.navigationBarTitle("", displayMode: .inline)

मुद्दा शुरू करना समाधान 1 तो बस नेविगेशन बार उपस्थिति बदल जाते हैं

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

प्रारंभिक नेविगेशन दृश्य रखने वाले दृश्य पर। अंतिम समाधान

यदि आप स्क्रीन से अपीयरेंस को स्क्रीन में बदलना चाहते हैं, तो उचित विचारों में उपस्थिति बदल दें


1
यह समाधान उपयोगी है
मुरिलो मेदिरोस

9

मैंने इस पृष्ठ पर उल्लिखित सभी समाधानों को भी आज़माया और केवल @graycampbell समाधान को अच्छी तरह से काम करने वाले एनिमेशन के साथ काम करने के लिए पाया। इसलिए मैंने एक मूल्य बनाने की कोशिश की जिसका उपयोग मैं पूरे ऐप में कर सकता हूं जिसे मैं hackingwithswift.com के उदाहरण से कहीं भी एक्सेस कर सकता हूं

मैंने एक ObservableObjectक्लास बनाई

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

और इसे इस SceneDelegateतरह से प्रारंभिक दृश्य में पास करें

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

तब ContentViewहम इस ऑब्जर्वेबल ऑब्जेक्ट का ट्रैक रख सकते हैं जैसे कि और इसके लिए एक लिंक बनाएं 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
            }
        }
    }
}

और फिर दूसरे दृश्य (SomeView) को एक्सेस करते समय, हम इसे फिर से इस तरह छिपाते हैं:

struct SomeView: View {
    @EnvironmentObject var navBarPrefs: NavBarPreferences

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

कार्य पूर्वावलोकन रखने के लिए पूर्वावलोकन की तरह NavBarPreferences जोड़ें ताकि:

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

2
का उपयोग कर @EnvironmentObject काफी बेहतर बजाय पूरे एप्लिकेशन में डेटा पारित करने के लिए है @State , तो मैं आपको और अधिक का जवाब पसंद करते हैं
Arafin रसेल

7

यह स्विफ्टयूआई ( अभी भी Xcode 11.2.1 के रूप में) में मौजूद एक बग है । मैंने ViewModifierमौजूदा जवाबों के कोड के आधार पर, इसे ठीक करने के लिए लिखा था :

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
इसके साथ, "स्विफ्ट टू बैक" इशारा अब काम नहीं कर रहा है
उर्कमन

6

आप इस तरह से देशी दृश्य प्रोटोकॉल का विस्तार कर सकते हैं :

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

तो बस कॉल जैसे:

ZStack {
    *YOUR CONTENT*
}
.hideNavigationBar()

5

मेरे लिए, मैं लागू करने गया था .navigationBarTitleकरने के लिए NavigationViewऔर के लिए नहीं Listअपराधी था। यह मेरे लिए Xcode 11.2.1 पर काम करता है:

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

नेविगेशन बार और शीर्ष पर कोई अंतराल के साथ सूची


5
पूछे गए प्रश्न के लिए अप्रासंगिक
अहमद साहिब

3
@AhmedSahib प्रश्न था "स्विफ्टयूआई नेवीगेशन व्यू में डिफ़ॉल्ट नेविगेशन बार स्थान को कैसे हटाया जाए" और मेरा कोड इसे पूरा करता है।
गेंकी

1
बहुत बढ़िया सलाह। अपने समाधान के लिए मुझे रिक्ति से छुटकारा पाने के लिए आंतरिक सूची में दो मॉडिफ़ायर लागू करने थे: .navigationBarTitle ("", displayMode: .automatic) .navigationBarHidden (सत्य) तब बाहरी नेविगेशन दृश्य पर मुझे लागू करना था: .navigationBarTitle (")। TITLE ", displayMode: .inline)
फ्रेंकस्टीन

4

मेरे लिए यह इसलिए था क्योंकि मैं अपने नेविगेशन व्यू को मौजूदा से आगे बढ़ा रहा था। एक के अंदर दूसरे के प्रभाव में। यदि आप एक नेविगेशन दृश्य से आ रहे हैं, तो आपको अगले के अंदर एक बनाने की आवश्यकता नहीं है जैसा कि आप पहले से ही एक नवगीत दृश्य के अंदर करते हैं।


2

@Graycampbell द्वारा उत्तर के समान लेकिन थोड़ा सरल:

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

शीर्षक को सेट करना आवश्यक है क्योंकि यह आपके द्वारा नेविगेट किए जाने वाले दृश्यों में पीछे बटन के बगल में दिखाया गया है।


1

स्विफ्टयूआई 2

नेविगेशन बार को कम जगह लेने के लिए एक समर्पित संशोधक है:

.navigationBarTitleDisplayMode(.inline)

नेविगेशन बार को छिपाने या इसके शीर्षक को सेट करने की आवश्यकता नहीं है।


0

वास्तव में @Vatsal Manot द्वारा दिए गए विचार से प्यार था, इसके लिए एक संशोधक बनाने के लिए। अपने जवाब से संपत्ति को
हटा isHiddenदेना, क्योंकि मुझे यह उपयोगी नहीं लगता क्योंकि संशोधक नाम से ही पता चलता है कि नेविगेशन बार को छिपाएं।

// 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

एक ऐप पर काम करते समय मुझे इसी तरह की समस्या हुई है जिसमें उपयोगकर्ता द्वारा लॉग इन करने के बाद एक टैब दृश्य प्रदर्शित किया जाना चाहिए।

जैसा कि @graycampbell ने अपनी टिप्पणी में सुझाव दिया है, एक TabView को एक नेविगेशन दृश्य में एम्बेड नहीं किया जाना चाहिए, अन्यथा "रिक्त स्थान" का उपयोग करते समय भी दिखाई देगा .navigationBarHidden(true)

मैंने ZStackनेवीगेशन व्यू को छिपाने के लिए एक का उपयोग किया । ध्यान दें कि इस सरल उदाहरण के लिए, मैं यूआई दृश्यता का प्रबंधन @Stateऔर उपयोग करता हूं @Binding, लेकिन आप कुछ अधिक जटिल जैसे कि एक पर्यावरण वस्तु का उपयोग करना चाह सकते हैं।

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

जब हम लॉग इन बटन दबाते हैं, तो प्रारंभिक पृष्ठ गायब हो जाता है, और डिटेल व्यू लोड हो जाता है। लॉग आउट बटन को टॉगल करने पर लॉगिन पेज फिर से दिखाई देता है

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

इस समस्या का मेरा समाधान @Genki और @Frankenstein द्वारा सुझाया गया था।

मैंने रिक्ति से छुटकारा पाने के लिए आंतरिक सूची में दो मॉडिफ़ायर लागू किए (नेवीगेशन व्यू नहीं):

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

बाहरी नेविगेशन दृश्य पर, फिर .navigationBarTitle("TITLE")शीर्षक सेट करने के लिए आवेदन किया गया।


1
यह कुछ भी नहीं करता है।
TruMan1

-8

NavigationViewअंदर डालने की कोशिश करो a GeometryReader

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

मैं अजीब व्यवहार का अनुभव कर चुका हूं जब NavigationViewरूट दृश्य था।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.