चौड़ाई और ऊँचाई अपने सुपरव्यू के लिए ऑटोलॉययूट प्रोग्रामेटिक रूप से उपयोग करने के बराबर है?


83

मैं नेट में बहुत सारे स्निपेट्स ढूंढ रहा हूं और मुझे अभी भी अपनी समस्या का जवाब नहीं मिल रहा है। मेरा प्रश्न यह है कि मेरे पास एक स्क्रॉलव्यू (एसवी) है और मैं स्क्रॉलव्यू (एसवी) के अंदर एक बटन जोड़ना चाहता हूं जो कि समान रूप से अपने सुपरवाइवे की ऊंचाई और ऊंचाई के साथ है जो स्क्रॉलव्यू (एसवी) है ताकि जब उपयोगकर्ता डिवाइस को घुमाएगा तो उसमें एक ही फ्रेम होगा स्क्रॉलव्यू (एसवी) की। NSLayout / NSLayoutConstraint कैसे करें? धन्यवाद

जवाबों:


125

अगर कोई स्विफ्ट समाधान की तलाश कर रहा है - मैं एक स्विफ्ट एक्सटेंशनUIView बनाऊंगा जिसके लिए आपको हर बार जब आप अपने सुपरवाइज सीमा के लिए एक उप-फ्रेम फ्रेम बाँधना चाहते हैं तो मदद मिलेगी:

स्विफ्ट 2:

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        superview.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    }

}

स्विफ्ट 3:

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    }
}

स्विफ्ट 4.2:

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        self.topAnchor.constraint(equalTo: superview.topAnchor, constant: 0).isActive = true
        self.bottomAnchor.constraint(equalTo: superview.bottomAnchor, constant: 0).isActive = true
        self.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: 0).isActive = true
        self.trailingAnchor.constraint(equalTo: superview.trailingAnchor, constant: 0).isActive = true

    }
}

तो बस इसे इस तरह से कॉल करें :

// after adding as a subview, e.g. `view.addSubview(subview)`
subview.bindFrameToSuperviewBounds()

जब एक .xib का उपयोग करके एक कस्टम UIView बनाते हैं, तो bindFrameToSuperviewBounds को 'आवश्यक init। (कोडर aDecoder)' के भीतर कहा जाना चाहिए। self.addSubview (self.view) के बाद
user1603721

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

यह स्विफ्ट 5 के लिए भी समाधान के रूप में काम करता है। मैं AutoLayout का उपयोग करके अपने कस्टम सब व्यू को पैरेंट व्यू आकार के अनुकूल नहीं बना सका। एक बार सबव्यू जोड़ने के बाद इसे इस्तेमाल करना आकर्षण का काम करता है।
टोनि_पीपू

स्विफ्ट 4.2 समाधान अच्छी तरह से काम करता है। आप इस constant: 0हिस्से को हटाकर इसे थोड़ा छोटा भी बना सकते हैं ।
ज़ीफ्राक्स

69

मुझे यकीन नहीं है कि यह करने के लिए सबसे कुशल तरीका है, लेकिन यह काम करता है ..

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.translatesAutoresizingMaskIntoConstraints = NO;
// initialize


[coverForScrolView addSubview:button];

NSLayoutConstraint *width =[NSLayoutConstraint
                                    constraintWithItem:button
                                    attribute:NSLayoutAttributeWidth
                                    relatedBy:0
                                    toItem:coverForScrolView
                                    attribute:NSLayoutAttributeWidth
                                    multiplier:1.0
                                    constant:0];
NSLayoutConstraint *height =[NSLayoutConstraint
                                     constraintWithItem:button
                                     attribute:NSLayoutAttributeHeight
                                     relatedBy:0
                                     toItem:coverForScrolView
                                     attribute:NSLayoutAttributeHeight
                                     multiplier:1.0
                                     constant:0];
NSLayoutConstraint *top = [NSLayoutConstraint
                                   constraintWithItem:button
                                   attribute:NSLayoutAttributeTop
                                   relatedBy:NSLayoutRelationEqual
                                   toItem:coverForScrolView
                                   attribute:NSLayoutAttributeTop
                                   multiplier:1.0f
                                   constant:0.f];
NSLayoutConstraint *leading = [NSLayoutConstraint
                                       constraintWithItem:button
                                       attribute:NSLayoutAttributeLeading
                                       relatedBy:NSLayoutRelationEqual
                                       toItem:coverForScrolView
                                       attribute:NSLayoutAttributeLeading
                                       multiplier:1.0f
                                       constant:0.f];
[coverForScrolView addConstraint:width];
[coverForScrolView addConstraint:height];
[coverForScrolView addConstraint:top];
[coverForScrolView addConstraint:leading];

4
यह उपयोग करने के लिए बहुत अधिक कुशल होगाNSLayoutConstraint.activateConstraints([width, height, top, leading])
बेरिक

आप उपयोग कर सकते हैं[coverForScrolView addConstraints:@[width, height, top, leading]];
इस्लाम Q.

1
यह ध्यान देने योग्य है (वर्षों बाद) यह कोड बहुत पुराना है । बाधाओं को जोड़ना अब बहुत आसान है - नीचे दिए गए 2017 के किसी भी उत्तर को देखें
Fattie

49

यह लिंक आपकी सहायता कर सकता है, निर्देशों का पालन कर सकता है: http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

संपादित करें:

कोड स्निपेट का उपयोग करें, जहां सबव्यू आपका सबवे है।

[subview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:|-0-[subview]-0-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(subview)]];
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-0-[subview]-0-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(subview)]];

4
इस मामले में, दृश्य प्रारूप भी हो सकता है V:|[subview]|औरH:|[subview]|
गुस्तावो बारबोसा

4
यह ध्यान देने योग्य है (वर्षों बाद) यह कोड बहुत पुराना है । बाधाओं को जोड़ना अब बहुत आसान है - नीचे दिए गए 2017 के किसी भी उत्तर को देखें
Fattie

19

addConstraintऔर removeConstraintयूआईवीवाई के लिए विधियां अपदस्थ होने जा रही हैं, इसलिए यह 'बाधा निर्माण उपयुक्तता' का उपयोग करने के लिए लायक है:

view.topAnchor.constraint(equalTo: superView.topAnchor, constant: 0).isActive = true
view.bottomAnchor.constraint(equalTo: superView.bottomAnchor, constant: 0).isActive = true
view.leadingAnchor.constraint(equalTo: superView.leadingAnchor, constant: 0).isActive = true
view.trailingAnchor.constraint(equalTo: superView.trailingAnchor, constant: 0).isActive = true

यह अच्छा काम करता है। आप इस constant: 0हिस्से को हटाकर इसे थोड़ा छोटा भी बना सकते हैं ।
Zyphrax

8

दृष्टिकोण # 1: वाया उविवि एक्सटेंशन

यहां स्विफ्ट 3+ में एक पूर्व-शर्त के बजाय (जो कंसोल में आसानी से नष्ट हो सकता है) के साथ अधिक कार्यात्मक दृष्टिकोण है । यह प्रोग्रामर त्रुटियों की रिपोर्ट करेगा जैसा कि विफल बनाता है।print

इस विस्तार को अपनी परियोजना में जोड़ें :

extension UIView {
    /// Adds constraints to the superview so that this view has same size and position.
    /// Note: This fails the build if the `superview` is `nil` – add it as a subview before calling this.
    func bindEdgesToSuperview() {
        guard let superview = superview else {
            preconditionFailure("`superview` was nil – call `addSubview(view: UIView)` before calling `bindEdgesToSuperview()` to fix this.")
        }
        translatesAutoresizingMaskIntoConstraints = false
        ["H:|-0-[subview]-0-|", "V:|-0-[subview]-0-|"].forEach { visualFormat in
            superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: visualFormat, options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        }
    }
}

अब बस इसे इस तरह से कॉल करें:

// after adding as a subview, e.g. `view.addSubview(subview)`
subview.bindEdgesToSuperview()

ध्यान दें कि उपरोक्त विधि पहले से ही मेरे HandyUIKit ढांचे में एकीकृत है, जो आपके प्रोजेक्ट में कुछ और आसान यूआई हेल्पर्स को भी जोड़ता है।


# 2 दृष्टिकोण: एक फ्रेमवर्क का उपयोग करना

यदि आप अपने प्रोजेक्ट में प्रोग्रामेटिक बाधाओं के साथ बहुत काम करते हैं, तो मैं आपको SnapKit को चेकआउट करने की सलाह देता हूं । यह बाधाओं को बहुत आसान और कम त्रुटि वाले कार्यों में बाधा बनाता है

अपने प्रोजेक्ट में SnapKit को शामिल करने के लिए डॉक्स में इंस्टॉलेशन निर्देशों का पालन करें । फिर इसे अपनी स्विफ्ट फ़ाइल के शीर्ष पर आयात करें:

import SnapKit

अब आप बस इसी के साथ एक ही चीज हासिल कर सकते हैं:

subview.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}

6

स्विफ्ट 3:

import UIKit

extension UIView {

    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    }

}

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

अरे @Dschee - मैं आपसे पूरी तरह सहमत हूँ, लेकिन हम "गलत" हैं। बेहतर या बदतर के लिए साइट पर "सर्वसम्मति" का दृष्टिकोण, आपके द्वारा यहां व्यक्त किए जाने के विपरीत है। meta.stackoverflow.com/questions/339024/… (मैं लगातार सर्वसम्मति के फैसले को अनदेखा करता हूं, जो समझदार है, उसे करें और फिर मोड से परेशानी में पड़ जाएं :))
Fattie

2

4 स्विफ्ट का उपयोग कर NSLayoutConstraint:

footerBoardImageView.translatesAutoresizingMaskIntoConstraints = false
let widthConstraint  = NSLayoutConstraint(item: yourview, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: superview, attribute: NSLayoutAttribute.width, multiplier: 1, constant: 0)
let heightConstraint = NSLayoutConstraint(item: yourview, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: superview, attribute: NSLayoutAttribute.height, multiplier: 1, constant: 0)
superview.addConstraints([widthConstraint, heightConstraint])

1

एक पूरक उत्तर के रूप में, और तीसरे पक्ष के पुस्तकालयों को शामिल करने का विरोध नहीं करने वालों में से एक, PureLayout पुस्तकालय यह करने के लिए एक विधि प्रदान करता है। एक बार लाइब्रेरी स्थापित हो जाने के बाद, यह उतना ही सरल है

myView.autoPinEdgesToSuperviewEdges()

अन्य पुस्तकालय हैं जो स्वाद के आधार पर समान कार्यक्षमता प्रदान कर सकते हैं, जैसे। चिनाई , कार्टोग्राफी


1

मैंने अन्य उत्तरों में से सर्वोत्तम तत्व निकाले हैं:

extension UIView {
  /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
  /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
  func bindFrameToSuperviewBounds() {
    guard let superview = self.superview else {
      print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
      return
    }

    self.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint.activate([
      self.topAnchor.constraint(equalTo: superview.topAnchor),
      self.bottomAnchor.constraint(equalTo: superview.bottomAnchor),
      self.leadingAnchor.constraint(equalTo: superview.leadingAnchor),
      self.trailingAnchor.constraint(equalTo: superview.trailingAnchor)
    ])
  }
}

आप इसे इस तरह से उपयोग कर सकते हैं, उदाहरण के लिए अपने कस्टम UIView में:

let myView = UIView()
myView.backgroundColor = UIColor.red

self.addSubview(myView)
myView.bindFrameToSuperviewBounds()

0

@ Dschee के समाधान के अनुसरण के रूप में, यहां स्विफ्ट 3.0 सिंटैक्स है: (कृपया ध्यान दें: यह मेरा समाधान नहीं है , मैंने इसे केवल स्विफ्ट 3.0 के लिए तय किया है)

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
}

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

मैं पूरी तरह से आपसे सहमत हूँ, @Dschee, लेकिन वहाँ है (मेरे लिए, बेतुका) मेटा पर टिप्पणी "हम ऐसा नहीं करते हैं इतने पर" कि ... meta.stackoverflow.com/questions/339024/...
fattie

@JoeBlow आपके लिंक के पीछे की चर्चा को पढ़ने के बाद मुझे वास्तव में लगता है कि यह भी समझ में आता है। मैं पैट्रिक हॉग की टिप्पणी (प्रश्न पर) से सहमत हूं, हालांकि मूल उत्तर पर टिप्पणी के साथ संयोजन में एक नया उत्तर दिया जाना चाहिए। इसके बाद मूल पोस्टर पर निर्भर है कि वह अपने उत्तर को अपडेट करे (भविष्य के अपवोट्स प्राप्त करने के लिए) या नहीं। लिंक के लिए आपको धन्यवाद!
जीहुत '

हुह, ठीक है यह सब एक बड़ा हिस्सा है कि मैं अतीत में एक वफादार हिट और धावक क्यों बना रहा। मैं अपना उत्तर लेता हूं, इसे वर्तमान सिंटैक्स में परिवर्तित करता हूं और अपने कोडिंग के साथ आगे बढ़ता हूं। इस तरह से पोस्ट करने का मुख्य कारण यह है कि जब मैंने स्विफ्ट सिखाया, तो मुझसे अक्सर पूछा जाता था कि स्विफ्ट के किसी भी संस्करण में समाधान कैसे खोजना है, क्योंकि नए कोडर्स को अपनी फ़ंक्शन घोषणाओं को अपडेट करने में परेशानी हो रही थी। यह हताशा के प्रमुख स्रोतों में से एक था, लेकिन दो कोड शैलियों के विपरीत होने का अवसर भी था। परिणाम के रूप में छात्र अन्य कोड स्निपेट में इसी तरह के बदलाव की भविष्यवाणी करने में सक्षम था।
जेम्स लार्कोम्ब

0

मुझे पूरी तरह से पर्यवेक्षण को कवर करने की आवश्यकता थी। अन्य उन्मुखीकरण परिवर्तनों के दौरान ऐसा नहीं करेंगे। इसलिए मैंने एक नया लिखा जो करता है - 20 के मनमाने आकार के गुणक का उपयोग करना। अपनी आवश्यकताओं को बदलने के लिए स्वतंत्र महसूस करें। यह भी ध्यान दें कि यह वास्तव में सबव्यू को पर्यवेक्षण से बहुत बड़ा बनाता है जो आवश्यकताओं से भिन्न हो सकता है।

extension UIView {
    func coverSuperview() {
        guard let superview = self.superview else {
            assert(false, "Error! `superview` was nil – call `addSubview(_ view: UIView)` before calling `\(#function)` to fix this.")
            return
        }
        self.translatesAutoresizingMaskIntoConstraints = false
        let multiplier = CGFloat(20.0)
        NSLayoutConstraint.activate([
            self.heightAnchor.constraint(equalTo: superview.heightAnchor, multiplier: multiplier),
            self.widthAnchor.constraint(equalTo: superview.widthAnchor, multiplier: multiplier),
            self.centerXAnchor.constraint(equalTo: superview.centerXAnchor),
            self.centerYAnchor.constraint(equalTo: superview.centerYAnchor),
            ])
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.