मैं प्रोग्रामेटिक रूप से सेफ एरिया लेआउट का उपयोग कैसे करूं?


99

चूँकि मैं अपने विचारों को बनाने के लिए स्टोरीबोर्ड का उपयोग नहीं करता हूं, मैं सोच रहा था कि क्या "सुरक्षित क्षेत्र गाइड्स का उपयोग करें" विकल्प प्रोग्राम या ऐसा कुछ है।

मैंने अपने विचारों को एंकर करने की कोशिश की है

view.safeAreaLayoutGuide

लेकिन वे iPhone X सिम्युलेटर में शीर्ष पायदान को ओवरलैप करते रहते हैं।



कैसे के बारे में view.safeAreaInsets? क्या आपने यह कोशिश की?
कार्तिकेयन बोस

@KarthikeyanBose हाँ मैंने दुर्भाग्य से कोई भाग्य नहीं किया।
फिलिप

मेरे लिये कार्य करता है। कोड कैसा दिखता है
डैनियल स्प्रिंगर

जवाबों:


155

यहाँ नमूना कोड है (संदर्भ से: सुरक्षित क्षेत्र लेआउट गाइड ):
यदि आप अपने बाधाओं बनाते हैं कोड में UIView की safeAreaLayoutGuide संपत्ति का उपयोग प्रासंगिक लेआउट एंकर प्राप्त करने के लिए। आइए कोड में उपरोक्त इंटरफ़ेस बिल्डर उदाहरण को फिर से बनाएँ, यह देखने के लिए कि यह कैसा दिखता है:

यह मानते हुए कि हमारे विचार नियंत्रक में एक संपत्ति के रूप में हमारे पास हरा दृश्य है:

private let greenView = UIView()

हमारे पास व्यूडलड से कहे जाने वाले विचारों और बाधाओं को स्थापित करने के लिए एक समारोह हो सकता है:

private func setupView() {
  greenView.translatesAutoresizingMaskIntoConstraints = false
  greenView.backgroundColor = .green
  view.addSubview(greenView)
}

हमेशा रूट दृश्य के लेआउटमार्गेगाइड का उपयोग करके अग्रणी और अनुगामी मार्जिन बाधाओं को बनाएं:

 let margins = view.layoutMarginsGuide
 NSLayoutConstraint.activate([
    greenView.leadingAnchor.constraint(equalTo: margins.leadingAnchor),
    greenView.trailingAnchor.constraint(equalTo: margins.trailingAnchor)
 ])

अब, जब तक आप iOS 11 और बाद में लक्षित नहीं कर रहे हैं, आपको पहले से उपलब्ध iOS संस्करणों के लिए सुरक्षित क्षेत्र लेआउट गाइड बाधाओं को लपेटना होगा और #available के साथ ऊपर और नीचे लेआउट गाइडों पर वापस गिरना होगा:

if #available(iOS 11, *) {
  let guide = view.safeAreaLayoutGuide
  NSLayoutConstraint.activate([
   greenView.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0),
   guide.bottomAnchor.constraintEqualToSystemSpacingBelow(greenView.bottomAnchor, multiplier: 1.0)
   ])
} else {
   let standardSpacing: CGFloat = 8.0
   NSLayoutConstraint.activate([
   greenView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: standardSpacing),
   bottomLayoutGuide.topAnchor.constraint(equalTo: greenView.bottomAnchor, constant: standardSpacing)
   ])
}

परिणाम:

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

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


यहाँ सुरक्षित क्षेत्र लेआउट गाइड के लिए Apple डेवलपर आधिकारिक दस्तावेज है


IPhone-X के लिए उपयोगकर्ता इंटरफ़ेस डिज़ाइन को संभालने के लिए सुरक्षित क्षेत्र आवश्यक है। सुरक्षित क्षेत्र लेआउट का उपयोग करके iPhone-X के लिए उपयोगकर्ता इंटरफ़ेस कैसे डिज़ाइन करें, इसके लिए बुनियादी दिशानिर्देश है


2
क्या यह उद्देश्य-सी में भी देना संभव होगा? ऐसा लगता है कि बस मुझे क्या चाहिए
टॉम हैमोंड

6
@TomHammond आपके लिए ऑब्जेक्टिव-सी में है stackoverflow.com/a/47076040/5638630
क्रुनाल

2
@ZonilyJame अब आपकी क्वेरी के बारे में - SaFeAreaLayout iOS विशिष्ट फ्रेमवर्क है (डिवाइस iPhoneX विशिष्ट नहीं), यह iOS 11 में टॉप-बॉटम लेआउट गाइड की जगह ले रहा है इसलिए हमें iOS के लिए डिवाइस के लिए उपयोग नहीं करना चाहिए। SafeAreaLayout सभी प्रकार के उपकरणों (iPhone-X और अन्य) के लिए डिज़ाइन का ध्यान रखता है। यदि आप अभी भी कोई प्रश्न / भ्रम रखते हैं, तो आप मुझसे अधिक जानकारी के लिए पूछ सकते हैं।
क्रुणाल

3
बहुत बढ़िया।
साभार

1
इसे सही उत्तर के रूप में क्यों स्वीकार किया जाता है? मैंने एक ठोस स्थिति स्थापित करने की कोशिश की - परिणाम पूरी तरह से यादृच्छिक है - नियंत्रण अप्रत्याशित स्थिति पर रखा गया है!
व्याचेस्लाव गेर्चिकोव

82

मैं वास्तव में इसके लिए एक एक्सटेंशन का उपयोग कर रहा हूं और नियंत्रित कर रहा हूं कि यह ios 11 है या नहीं।

extension UIView {

  var safeTopAnchor: NSLayoutYAxisAnchor {
    if #available(iOS 11.0, *) {
      return self.safeAreaLayoutGuide.topAnchor
    }
    return self.topAnchor
  }

  var safeLeftAnchor: NSLayoutXAxisAnchor {
    if #available(iOS 11.0, *){
      return self.safeAreaLayoutGuide.leftAnchor
    }
    return self.leftAnchor
  }

  var safeRightAnchor: NSLayoutXAxisAnchor {
    if #available(iOS 11.0, *){
      return self.safeAreaLayoutGuide.rightAnchor
    }
    return self.rightAnchor
  }

  var safeBottomAnchor: NSLayoutYAxisAnchor {
    if #available(iOS 11.0, *) {
      return self.safeAreaLayoutGuide.bottomAnchor
    }
    return self.bottomAnchor
  }
}

यह जाने के लिए एक सरल तरीका है और चाल है। विचार के लिए धन्यवाद।
alper_k

यह ऐसा करने के लिए एक सरल अभी तक अच्छा तरीका है! के self.safeAreaLayoutGuideबजाय के उपयोग पर ध्यान दें self.layoutMarginsGuide। इस उत्तर में उपयोग किए जाने वाले सुरक्षित ने मेरे लिए सुरक्षित क्षेत्र में रहने के लिए सही तरीके से काम किया! एक बात मैं बदल रहा सुझाव है कि उपयोग करने के लिए किया जाएगा leadingAnchorऔर trailingAnchorके बजाय leftAnchorऔर rightAnchor। वाहवाही!
प्रणॉय सी

22

SafeAreaLayoutGuideहै UIViewसंपत्ति,

SafeAreaLayoutGuide का शीर्ष दृश्य के बिना शीर्ष वाले ऊपरी किनारे को इंगित करता है (उदाहरण के लिए, स्थिति पट्टी या नेविगेशन बार के पीछे नहीं, यदि मौजूद है)। इसी तरह अन्य किनारों के लिए।

safeAreaLayoutGuideगोल कोनों, नेविगेशन बार, टैब बार, टूलबार और अन्य पूर्वजों के विचारों से क्लिपिंग / ओवरलैपिंग से बचने के लिए हमारी वस्तुओं का उपयोग करें ।

हम safeAreaLayoutGuideक्रमशः ऑब्जेक्ट बना सकते हैं और ऑब्जेक्ट बाधाओं को सेट कर सकते हैं ।

पोर्ट्रेट + लैंडस्केप के लिए बाधाएं हैं -

पोर्ट्रेट छवि

लैंडस्केप इमेज

        self.edgesForExtendedLayout = []//Optional our as per your view ladder

        let newView = UIView()
        newView.backgroundColor = .red
        self.view.addSubview(newView)
        newView.translatesAutoresizingMaskIntoConstraints = false
        if #available(iOS 11.0, *) {
            let guide = self.view.safeAreaLayoutGuide
            newView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
            newView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
            newView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
            newView.heightAnchor.constraint(equalToConstant: 100).isActive = true

        }
        else {
            NSLayoutConstraint(item: newView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: 0).isActive = true
            NSLayoutConstraint(item: newView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true
            NSLayoutConstraint(item: newView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true

            newView.heightAnchor.constraint(equalToConstant: 100).isActive = true
        }

UILayoutGuide

safeAreaLayoutGuide


2
कभी भी सेटअप में बाधा न डालें viewDidAppear, जब तक कि आप पूरी तरह से नहीं जानते कि आप क्या कर रहे हैं। viewDidAppearकई बार कहा जाता है और इसलिए, हर बार जब भी बुलाया जाता है, तो आपके अवरोधों को दोहराया जाएगा।
येविन दुबिनिन

हाँ! , संपादित उत्तर, आप अपने उपयोग के मामले के रूप में उपयोग कर सकते हैं।
जैक

14

आप में से जो मेरी तरह ही SnapKit का उपयोग करते हैं, उनके समाधान आपके अवरोधों को view.safeAreaLayoutGuideपसंद करने के लिए लंगर डाल रहे हैं:

yourView.snp.makeConstraints { (make) in
    if #available(iOS 11.0, *) {
        //Bottom guide
        make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottomMargin)
        //Top guide
        make.top.equalTo(view.safeAreaLayoutGuide.snp.topMargin)
        //Leading guide
        make.leading.equalTo(view.safeAreaLayoutGuide.snp.leadingMargin)
        //Trailing guide
        make.trailing.equalTo(view.safeAreaLayoutGuide.snp.trailingMargin)

     } else {
        make.edges.equalToSuperview()
     }
}

1
बहुत बढ़िया जवाब। यह थोड़ा अधिक कॉम्पैक्ट आप कह सकते हैं बनाने के लिए: #available अगर (आईओएस 11.0, *) {make.edges.equalTo (view.safeAreaLayoutGuide.snp.margins)}
डॉन Miguel

7

मैं लेआउट में बड़े और पीछे आने वाली मार्जिन बाधाओं को जोड़ने के बजाय इसका उपयोग कर रहा हूं।

UILayoutGuide *safe = self.view.safeAreaLayoutGuide;
yourView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
                                           [safe.trailingAnchor constraintEqualToAnchor:yourView.trailingAnchor],
                                           [yourView.leadingAnchor constraintEqualToAnchor:safe.leadingAnchor],
                                           [yourView.topAnchor constraintEqualToAnchor:safe.topAnchor],
                                           [safe.bottomAnchor constraintEqualToAnchor:yourView.bottomAnchor]
                                          ]];

क्रुनाल के जवाब से ios 11 के निचले संस्करण के विकल्प को भी देखें।


सुनिश्चित करें कि आप पहले से ही अपना दृश्य सुपरव्यू में जोड़ लें। यह एक सरल उदाहरण के रूप में मेरे कोड में स्वयं है।
टोनी TRAN

6

का प्रयोग करें UIWindowया UIViewकीsafeAreaInsets .bottom .top .left .right

// #available(iOS 11.0, *)
// height - UIApplication.shared.keyWindow!.safeAreaInsets.bottom

// On iPhoneX
// UIApplication.shared.keyWindow!.safeAreaInsets.top =  44
// UIApplication.shared.keyWindow!.safeAreaInsets.bottom = 34

// Other devices
// UIApplication.shared.keyWindow!.safeAreaInsets.top =  0
// UIApplication.shared.keyWindow!.safeAreaInsets.bottom = 0

// example
let window = UIApplication.shared.keyWindow!
let viewWidth = window.frame.size.width
let viewHeight = window.frame.size.height - window.safeAreaInsets.bottom
let viewFrame = CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight)
let aView = UIView(frame: viewFrame)
aView.backgroundColor = .red
view.addSubview(aView)
aView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

3
यदि आपका दृश्य AutoLayout का उपयोग नहीं कर रहा है तो यह जाने का तरीका है।
जोनाथन कैबरेरा

4

दृश्य प्रारूप के साथ बाधाओं का उपयोग करें और आपको मुफ्त में सुरक्षित क्षेत्र के लिए सम्मान मिलता है।

class ViewController: UIViewController {

    var greenView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()
        greenView.backgroundColor = .green
        view.addSubview(greenView)
    }
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()

        greenView.translatesAutoresizingMaskIntoConstraints = false
        let views : [String:Any] = ["greenView":greenView]
        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[greenView]-|", options: [], metrics: nil, views: views))
        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[greenView]-|", options: [], metrics: nil, views: views))
    }
}

परिणाम


2
कृपया नीचे मतदान करते समय एक टिप्पणी प्रदान करें, इसलिए हम सभी सीख सकते हैं यदि कोई ऐसा मामला है जहां यह तकनीक लागू नहीं होती है। धन्यवाद!
एटॉमिक बुलियन

यह काम करता है, मैं भी दृश्य प्रारूप समाधान की तरह! धन्यवाद! लेकिन क्या यह सभी आईओएस संस्करणों के लिए काम करता है?
PaFi

4

उद्देश्य-सी के लिए सुरक्षित क्षेत्र विस्तार

@implementation UIView (SafeArea)

- (NSLayoutAnchor *)safeTopAnchor{

    if (@available(iOS 11.0, *)){
        return self.safeAreaLayoutGuide.topAnchor;
    } else {
        return self.topAnchor;
    }

}


- (NSLayoutAnchor *)safeBottomAnchor{

    if (@available(iOS 11.0, *)) {
        return self.safeAreaLayoutGuide.bottomAnchor;
    } else {
        return self.bottomAnchor;
    }

}

@end

यह काम नहीं करता है (स्विफ्ट 4.2, आईओएस 12)। परिणाम स्थिति बार को नजरअंदाज करता है
व्याचेस्लाव गेरिकोव

2

स्विफ्ट 4.2 और 5.0। मान लीजिए कि आप व्यूबग पर लीडिंग, ट्रेलिंग, टॉप और बॉटम की बाधाओं को जोड़ना चाहते हैं। तो, आप नीचे दिए गए कोड का उपयोग कर सकते हैं।

let guide = self.view.safeAreaLayoutGuide
viewBg.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
viewBg.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
viewBg.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
viewBg.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true

1

यह एक्सटेंशन आपको इसके पर्यवेक्षण और पर्यवेक्षण के लिए एक UIVIew को नियंत्रित करने में मदद करता है + सुरक्षित:

extension UIView {

    ///Constraints a view to its superview
    func constraintToSuperView() {
        guard let superview = superview else { return }
        translatesAutoresizingMaskIntoConstraints = false

        topAnchor.constraint(equalTo: superview.topAnchor).isActive = true
        leftAnchor.constraint(equalTo: superview.leftAnchor).isActive = true
        bottomAnchor.constraint(equalTo: superview.bottomAnchor).isActive = true
        rightAnchor.constraint(equalTo: superview.rightAnchor).isActive = true
    }

    ///Constraints a view to its superview safe area
    func constraintToSafeArea() {
        guard let superview = superview else { return }
        translatesAutoresizingMaskIntoConstraints = false

        topAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.topAnchor).isActive = true
        leftAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.leftAnchor).isActive = true
        bottomAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.bottomAnchor).isActive = true
        rightAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.rightAnchor).isActive = true
    }

}

0

आप https://www.raywenderlich.com/174078/auto-layout-visual-format-language-tutorial-2 के अनुसार यहां दिए गए व्यू.safeAreaInsets का उपयोग कर सकते हैं ।

कोड नमूना (रेवेंडरलाइच.कॉम से लिया गया):

override func viewSafeAreaInsetsDidChange() {
  super.viewSafeAreaInsetsDidChange()

  if !allConstraints.isEmpty {
    NSLayoutConstraint.deactivate(allConstraints)
    allConstraints.removeAll()
  }

  let newInsets = view.safeAreaInsets
  let leftMargin = newInsets.left > 0 ? newInsets.left : Metrics.padding
  let rightMargin = newInsets.right > 0 ? newInsets.right : Metrics.padding
  let topMargin = newInsets.top > 0 ? newInsets.top : Metrics.padding
  let bottomMargin = newInsets.bottom > 0 ? newInsets.bottom : Metrics.padding

  let metrics = [
    "horizontalPadding": Metrics.padding,
    "iconImageViewWidth": Metrics.iconImageViewWidth,
    "topMargin": topMargin,
    "bottomMargin": bottomMargin,
    "leftMargin": leftMargin,
    "rightMargin": rightMargin]
}


let views: [String: Any] = [
  "iconImageView": iconImageView,
  "appNameLabel": appNameLabel,
  "skipButton": skipButton,
  "appImageView": appImageView,
  "welcomeLabel": welcomeLabel,
  "summaryLabel": summaryLabel,
  "pageControl": pageControl]

let iconVerticalConstraints = NSLayoutConstraint.constraints(
  withVisualFormat: "V:|-topMargin-[iconImageView(30)]",
  metrics: metrics,
  views: views)
allConstraints += iconVerticalConstraints

let topRowHorizontalFormat = """
  H:|-leftMargin-[iconImageView(iconImageViewWidth)]-[appNameLabel]-[skipButton]-rightMargin-|
  """
...
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.