सुरक्षित क्षेत्र इनसेट ऊपर और नीचे की ऊँचाई प्राप्त करें


178

नए iPhone X पर, असुरक्षित क्षेत्रों के लिए शीर्ष और नीचे दोनों ऊंचाई प्राप्त करने का सबसे उचित तरीका क्या होगा?

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

जवाबों:


365

इसे इस्तेमाल करे :

में उद्देश्य सी

if (@available(iOS 11.0, *)) {
    UIWindow *window = UIApplication.sharedApplication.keyWindow;
    CGFloat topPadding = window.safeAreaInsets.top;
    CGFloat bottomPadding = window.safeAreaInsets.bottom;
}

में स्विफ्ट

if #available(iOS 11.0, *) {
    let window = UIApplication.shared.keyWindow
    let topPadding = window?.safeAreaInsets.top
    let bottomPadding = window?.safeAreaInsets.bottom
}

1
@KrutikaSonawala निचलापैड + 10 (आपका मान)
user6788419

12
यह मेरे लिए काम करने के लिए प्रतीत नहीं होता है - UIApplication.sared.keyWindow .safeAreaInsets के मान को प्रिंट करके सभी 0s लौटाता है। कोई विचार?
हाई

2
मैंने किया, मैं किसी भी दृश्य के safeAreaLayoutGuides के खिलाफ विवश कर सकता हूं, लेकिन सीधे कुंजी विंडो के मूल्य को प्रिंट कर रहा हूं ।AreaInsets बस एक शून्य आयत लौटाता है। यह समस्याग्रस्त है क्योंकि मुझे मैन्युअल रूप से एक दृश्य को कसने की आवश्यकता है जिसे कुंजी विंडो में जोड़ा गया है, लेकिन रूट व्यू कंट्रोलर के दृष्टिकोण में नहीं है।
हाई

6
मेरे लिए, keyWindowहमेशा nilऐसा था कि मैंने इसे बदल windows[0]दिया और ?वैकल्पिक चैनिंग से हटा दिया , फिर इसने काम किया।
जॉर्ज_ए 17

2
यह केवल तभी काम कर रहा है जब एक नियंत्रक का दृष्टिकोण पहले ही प्रकट हो चुका है।
वान्या १

84

लेआउट गाइड के बीच की ऊँचाई प्राप्त करने के लिए आप बस करते हैं

let guide = view.safeAreaLayoutGuide
let height = guide.layoutFrame.size.height

तो full frame height = 812.0,safe area height = 734.0

नीचे उदाहरण है जहां हरे रंग के दृश्य का फ्रेम है guide.layoutFrame

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


धन्यवाद कि वह लीड था जिसके बारे में मैं भी सोच रहा था। मुझे नहीं लगता कि एक अधिक विश्वसनीय समाधान है। लेकिन इसके साथ मुझे केवल पूर्ण असुरक्षित ऊंचाई मिलती है, है ना? प्रत्येक क्षेत्रों के लिए दो ऊंचाई नहीं?
ट्यूबलेब

2
एक बार विचार सामने आने के बाद यह आपको सही उत्तर देगा
लादिस्लाव

2
वास्तव में @ user6788419 का जवाब बहुत अच्छा और छोटा लगता है।
तुललेब

मैं उस कोड के साथ 812.0 की ऊंचाई प्राप्त कर रहा हूं, एक नियंत्रक के दृष्टिकोण का उपयोग करके। इसलिए मैं उपयोग कर रहा हूं UIApplication.sharedApplication.keyWindow.safeAreaLayoutGuide.layoutFrame, जिसमें सुरक्षित फ्रेम है।
फेरन मायलिनच

1
@FerranMaylinch सुनिश्चित नहीं हैं कि आप कहाँ ऊँचाई की जाँच कर रहे हैं, लेकिन मेरे पास 812 भी थे, जो कि दृश्यमान होने से पहले मान की जाँच करने के कारण निकले। उस स्थिति में ऊंचाइयां समान होंगी "यदि दृश्य वर्तमान में दृश्य पदानुक्रम में स्थापित नहीं है, या अभी तक ऑनस्क्रीन दिखाई नहीं दे रहा है, तो लेआउट मार्गदर्शक किनारे दृश्य के किनारों के बराबर हैं" डेवलपर.apple.com/documentation/ uikit / uiview /…
निकोलस हार्लेन

81

स्विफ्ट 4, 5

किसी सुरक्षित क्षेत्र के एंकर को देखने के लिए बाधाओं का उपयोग करते हुए व्यू कंट्रोलर के जीवनचक्र में कहीं भी किया जा सकता है क्योंकि वे एपीआई द्वारा पंक्तिबद्ध होते हैं और दृश्य को मेमोरी में लोड होने के बाद हैंडल किया जाता है। हालाँकि, सुरक्षित-क्षेत्र मान प्राप्त करने के लिए व्यू कंट्रोलर के जीवनचक्र के अंत की प्रतीक्षा करने की आवश्यकता होती है, जैसे viewDidLayoutSubviews()

यह किसी भी दृश्य नियंत्रक में प्लग करता है:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    let topSafeArea: CGFloat
    let bottomSafeArea: CGFloat

    if #available(iOS 11.0, *) {
        topSafeArea = view.safeAreaInsets.top
        bottomSafeArea = view.safeAreaInsets.bottom
    } else {
        topSafeArea = topLayoutGuide.length
        bottomSafeArea = bottomLayoutGuide.length
    }

    // safe area values are now available to use
}

मैं इस पद्धति को विंडो से दूर होने के लिए पसंद करता हूं (जब संभव हो) क्योंकि यह है कि एपीआई कैसे डिज़ाइन किया गया था और इससे भी महत्वपूर्ण बात यह है कि मूल्यों को सभी दृश्य परिवर्तनों के दौरान अपडेट किया जाता है, जैसे डिवाइस ओरिएंटेशन परिवर्तन।

हालाँकि, कुछ कस्टम प्रस्तुत दृश्य नियंत्रक उपरोक्त विधि का उपयोग नहीं कर सकते हैं (मुझे संदेह है क्योंकि वे क्षणिक कंटेनर विचारों में हैं)। ऐसे मामलों में, आप रूट व्यू कंट्रोलर से मान प्राप्त कर सकते हैं, जो हमेशा वर्तमान व्यू कंट्रोलर के जीवनचक्र में कहीं भी उपलब्ध होगा।

anyLifecycleMethod()
    guard let root = UIApplication.shared.keyWindow?.rootViewController else {
        return
    }
    let topSafeArea: CGFloat
    let bottomSafeArea: CGFloat

    if #available(iOS 11.0, *) {
        topSafeArea = root.view.safeAreaInsets.top
        bottomSafeArea = root.view.safeAreaInsets.bottom
    } else {
        topSafeArea = root.topLayoutGuide.length
        bottomSafeArea = root.bottomLayoutGuide.length
    }

    // safe area values are now available to use
}

3
कृपया topSafeArea का उपयोग करते हुए घोषित करें: इसके बजाय CGFloat!
गुसूताफू

उपयोग करने से बचें viewDidLayoutSubviews(जिसे कई बार कहा जा सकता है), यहाँ एक समाधान है जो इसमें भी काम करेगा viewDidLoad: stackoverflow.com/a/53864017/7767664
user924

@ user924 तब मानों को अद्यतन नहीं किया जाएगा जब सुरक्षित क्षेत्रों में बदलाव होता है (यानी डबल-हाइट स्टेटस बार)
bsod

@bsod तो यह बेहतर stackoverflow.com/a/3420550/7767664 होगा (क्योंकि यह केवल स्टेटस बार और अन्य विचारों के लिए नहीं है)
user924

या ऐप डेलीगेट के माध्यम से जाने के बजाय आप व्यू कंट्रोलर में निर्मित सुरक्षित क्षेत्र एपीआई ऐप्पल का उपयोग कर सकते हैं।
bsod

21

यहां किसी भी अन्य उत्तर ने मेरे लिए काम नहीं किया, लेकिन यह किया।

var topSafeAreaHeight: CGFloat = 0
var bottomSafeAreaHeight: CGFloat = 0

  if #available(iOS 11.0, *) {
    let window = UIApplication.shared.windows[0]
    let safeFrame = window.safeAreaLayoutGuide.layoutFrame
    topSafeAreaHeight = safeFrame.minY
    bottomSafeAreaHeight = window.frame.maxY - safeFrame.maxY
  }

1
आप कोड व्यू कंट्रोलर जीवन चक्र के किसी भी भाग में काम करेंगे। यदि आप view.safeAreaInsets.top का उपयोग करना चाहते हैं, तो आपको यह सुनिश्चित करने की आवश्यकता है कि आप इसे viewDidAppear या बाद में कॉल करें। ViewDidLoad में, आपको view.safeAreaInsets.top सही मान के साथ नहीं मिलेगा क्योंकि यह अभी तक आरंभ नहीं हुआ है।
user3204765

1
अब तक का सर्वश्रेष्ठ उत्तर
रिक्को डे

17

यहाँ सभी उत्तर उपयोगी हैं, उन सभी को धन्यवाद जिन्होंने मदद की पेशकश की।

हालाँकि जैसा कि मैं देख रहा हूँ कि सुरक्षित क्षेत्र विषय थोड़ा भ्रमित है जो अच्छी तरह से प्रलेखित नहीं होगा।

इसलिए मैं इसे यहीं पर संक्षेप में प्रस्तुत करूंगा ताकि इसे समझना आसान हो सके safeAreaInsets, safeAreaLayoutGuideऔर LayoutGuide

IOS 7 में, Apple ने प्रॉपर्टीज topLayoutGuideऔर bottomLayoutGuideप्रॉपर्टीज पेश कीं UIViewController, उन्होंने आपको अपनी कंटेंट को UIKit बार जैसे कि स्टेटस, नेविगेशन या टैब बार से छुपाकर रखने के लिए अड़चनें पैदा करने की अनुमति दी। कंटेंट पर कॉन्ट्रैक्ट्स को निर्दिष्ट करने के लिए इन लेआउट गाइड्स से संभव था, इसे टालें। ऊपर या नीचे नेविगेशन तत्वों (UIKit बार, स्टेटस बार, नेवी या टैब बार ...) द्वारा छिपा होना।

उदाहरण के लिए यदि आप एक तालिका बनाना चाहते हैं तो शीर्ष स्क्रीन से शुरू होता है, जो आपने कुछ इस तरह किया है:

self.tableView.contentInset = UIEdgeInsets(top: -self.topLayoutGuide.length, left: 0, bottom: 0, right: 0)

IOS 11 में Apple ने इन संपत्तियों को एक सुरक्षित क्षेत्र लेआउट गाइड के साथ बदल दिया है

Apple के अनुसार सुरक्षित क्षेत्र

सुरक्षित क्षेत्र आपके विचारों को समग्र इंटरफ़ेस के दृश्य भाग के भीतर रखने में मदद करते हैं। यूआईआईआईटी-परिभाषित दृश्य नियंत्रक आपकी सामग्री के शीर्ष पर विशेष विचार रख सकते हैं। उदाहरण के लिए, एक नेविगेशन नियंत्रक अंतर्निहित दृश्य नियंत्रक की सामग्री के शीर्ष पर एक नेविगेशन बार प्रदर्शित करता है। यहां तक ​​कि जब इस तरह के विचार आंशिक रूप से पारदर्शी होते हैं, तब भी वे उस सामग्री को रोक देते हैं जो उनके नीचे है। टीवीओएस में, सुरक्षित क्षेत्र में स्क्रीन के ओवरस्कैन इनसेट भी शामिल होते हैं, जो स्क्रीन के बेज़ेल द्वारा कवर किए गए क्षेत्र का प्रतिनिधित्व करते हैं।

नीचे, एक सुरक्षित क्षेत्र iPhone 8 और iPhone X-Series में हाइलाइट किया गया है:

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

की safeAreaLayoutGuideसंपत्ति हैUIView

की ऊंचाई पाने के लिए safeAreaLayoutGuide:

extension UIView {
   var safeAreaHeight: CGFloat {
       if #available(iOS 11, *) {
        return safeAreaLayoutGuide.layoutFrame.size.height
       }
       return bounds.height
  }
}

जो आपके चित्र में एरो की ऊँचाई को लौटा देगा।

अब, शीर्ष "पायदान" और नीचे होम स्क्रीन सूचक ऊंचाइयों को प्राप्त करने के बारे में क्या?

यहां हम इसका उपयोग करेंगे safeAreaInsets

एक दृश्य का सुरक्षित क्षेत्र नेविगेशन बार, टैब बार, टूलबार और अन्य पूर्वजों द्वारा कवर किए गए क्षेत्र को दर्शाता है जो एक दृश्य नियंत्रक के दृश्य को अस्पष्ट करते हैं। (टीवीओएस में, सुरक्षित क्षेत्र स्क्रीन के बेज़ेल द्वारा कवर नहीं किए गए क्षेत्र को दर्शाता है।) आप इस संपत्ति में इनसेट को दृश्य की सीमा आयत पर लगाकर दृश्य के लिए सुरक्षित क्षेत्र प्राप्त करते हैं। यदि दृश्य वर्तमान में दृश्य पदानुक्रम में स्थापित नहीं किया गया है, या अभी तक ऑनस्क्रीन दिखाई नहीं दे रहा है, तो इस गुण में किनारे वाले इनसेट 0 हैं।

निम्नलिखित असुरक्षित क्षेत्र दिखाएगा और iPhone 8 और iPhone X-Series में से एक पर किनारों से दूरी होगी।

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

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

अब, यदि नेविगेशन बार जोड़ा गया है

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

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

तो, अब असुरक्षित क्षेत्र ऊंचाई कैसे प्राप्त करें? हम उपयोग करेंगेsafeAreaInset

हालांकि वे समाधान के लिए एक महत्वपूर्ण बात में भिन्न हैं,

पेहला:

self.view.safeAreaInsets

EdgeInsets को लौटाएगा, अब आप इनसेट्स को जानने के लिए ऊपर और नीचे तक पहुंच सकते हैं,

दूसरा:

UIApplication.shared.windows.first{$0.isKeyWindow }?.safeAreaInsets

पहला वह जिसे आप इनसेट देख रहे हैं, इसलिए यदि कोई नेविगेशन बार है तो उस पर विचार किया जाएगा, हालांकि दूसरा वह जो आप विंडो के सेफ एक्सेस पर पहुंच रहे हैं। इसलिए नेविगेशन बार पर विचार नहीं किया जाएगा।


5

IOS 11 में एक विधि है जो बताती है कि सेफरा कब बदल गया है।

override func viewSafeAreaInsetsDidChange() {
    super.viewSafeAreaInsetsDidChange()
    let top = view.safeAreaInsets.top
    let bottom = view.safeAreaInsets.bottom
}

2

मैं CocoaPods चौखटे के साथ काम कर रहा हूं और अगर UIApplication.sharedयह अनुपलब्ध है तो मैं safeAreaInsetsदृश्य के रूप में उपयोग करता हूं window:

if #available(iOS 11.0, *) {
    let insets = view.window?.safeAreaInsets
    let top = insets.top
    let bottom = insets.bottom
}

2

safeAreaLayoutGuide जब दृश्य ऑनस्क्रीन दिखाई देता है, तो यह मार्गदर्शिका दृश्य के उस भाग को दर्शाती है, जो नेविगेशन बार, टैब बार, टूलबार और अन्य पूर्वजों के विचारों द्वारा कवर नहीं किया गया है। (टीवीओएस में, सुरक्षित क्षेत्र स्क्रीन के बेज़ल को कवर नहीं करने वाले क्षेत्र को दर्शाता है।) यदि दृश्य वर्तमान में दृश्य पदानुक्रम में स्थापित नहीं है, या अभी तक ऑनस्क्रीन दिखाई नहीं दे रहा है, तो लेआउट गाइड किनारे दृश्य के किनारों के बराबर हैं।

फिर स्क्रीनशॉट में लाल तीर की ऊंचाई पाने के लिए:

self.safeAreaLayoutGuide.layoutFrame.size.height

2

स्विफ्ट 5, एक्सकोड 11.4

`UIApplication.shared.keyWindow` 

यह डेप्रिसिएशन की चेतावनी देगा। '' keyWindow 'को iOS 13.0 में पदावनत किया गया: इसका उपयोग उन अनुप्रयोगों के लिए नहीं किया जाना चाहिए जो कई दृश्यों का समर्थन करते हैं क्योंकि यह कनेक्टेड दृश्यों की वजह से सभी जुड़े दृश्यों में एक महत्वपूर्ण विंडो देता है। मैं इस तरह का उपयोग करता हूं।

extension UIView {

    var safeAreaBottom: CGFloat {
         if #available(iOS 11, *) {
            if let window = UIApplication.shared.keyWindowInConnectedScenes {
                return window.safeAreaInsets.bottom
            }
         }
         return 0
    }

    var safeAreaTop: CGFloat {
         if #available(iOS 11, *) {
            if let window = UIApplication.shared.keyWindowInConnectedScenes {
                return window.safeAreaInsets.top
            }
         }
         return 0
    }
}

extension UIApplication {
    var keyWindowInConnectedScenes: UIWindow? {
        return windows.first(where: { $0.isKeyWindow })
    }
}

1

ऑब्जेक्टिव-सी कौन समस्या थी जब keyWindow के बराबर है शून्य । बस ऊपर कोड को viewDidAppear में रखें (viewDidLoad में नहीं)


1
UIWindow *window = [[[UIApplication sharedApplication] delegate] window]; 
CGFloat fBottomPadding = window.safeAreaInsets.bottom;

1

स्विफ्ट 5 एक्सटेंशन

इसे एक्सटेंशन के रूप में इस्तेमाल किया जा सकता है और इसके साथ बुलाया जा सकता है: UIApplication.topSafeAreaHeight

extension UIApplication {
    static var topSafeAreaHeight: CGFloat {
        var topSafeAreaHeight: CGFloat = 0
         if #available(iOS 11.0, *) {
               let window = UIApplication.shared.windows[0]
               let safeFrame = window.safeAreaLayoutGuide.layoutFrame
               topSafeAreaHeight = safeFrame.minY
             }
        return topSafeAreaHeight
    }
}

UIApplication का विस्तार वैकल्पिक है, UIView का विस्तार हो सकता है या जो भी पसंद किया जाता है, या शायद एक वैश्विक फ़ंक्शन भी बेहतर है।


0

अधिक गोल दृष्टिकोण

  import SnapKit

  let containerView = UIView()
  containerView.backgroundColor = .red
  self.view.addSubview(containerView)
  containerView.snp.remakeConstraints { (make) -> Void in
        make.width.top.equalToSuperView()
        make.top.equalTo(self.view.safeArea.top)
        make.bottom.equalTo(self.view.safeArea.bottom)
  }




extension UIView {
    var safeArea: ConstraintBasicAttributesDSL {
        if #available(iOS 11.0, *) {
            return self.safeAreaLayoutGuide.snp
        }
        return self.snp
    }


    var isIphoneX: Bool {

        if #available(iOS 11.0, *) {
            if topSafeAreaInset > CGFloat(0) {
                return true
            } else {
                return false
            }
        } else {
            return false
        }

    }

    var topSafeAreaInset: CGFloat {
        let window = UIApplication.shared.keyWindow
        var topPadding: CGFloat = 0
        if #available(iOS 11.0, *) {
            topPadding = window?.safeAreaInsets.top ?? 0
        }

        return topPadding
    }

    var bottomSafeAreaInset: CGFloat {
        let window = UIApplication.shared.keyWindow
        var bottomPadding: CGFloat = 0
        if #available(iOS 11.0, *) {
            bottomPadding = window?.safeAreaInsets.bottom ?? 0
        }

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