<p>θέλω να χρησιμοποιήσω το autolayout για το μέγεθος και τη διάταξη μιας προβολής με τρόπο που θυμίζει τη λειτουργία περιεχομένου uiimageview.</p><p>έχω υποκλέψει μέσα σε μια προβολή κοντέινερ στο interface builder. το subview έχει κάποια εγγενή αναλογία που θέλω να σεβαστώ. το μέγεθος της προβολής του κοντέινερ είναι άγνωστο μέχρι την εκτέλεση.</p><p>εάν ο λόγος πλευρών της προβολής δοχείου είναι ευρύτερος από το υποκείμενο, τότε θέλω το ύψος του υποσέλιδου να ισούται με το ύψος της γονικής προβολής.</p><p>αν ο λόγος πλευρών της προβολής δοχείου είναι ψηλότερος από το υποκείμενο, τότε θέλω το πλάτος του υποσέλιδου να ισούται με το πλάτος της γονικής προβολής.</p><p>σε κάθε περίπτωση, εύχομαι η υποενότητα να είναι κεντραρισμένη οριζόντια και κάθετα μέσα στην προβολή του δοχείου.</p><p>υπάρχει τρόπος να επιτευχθεί αυτό χρησιμοποιώντας τους περιορισμούς autolayout στο xcode 6 ή σε προηγούμενη έκδοση; χρησιμοποιώντας ιδανικά το interface builder, αλλά αν όχι ίσως είναι δυνατόν να οριστούν αυτοί οι περιορισμοί προγραμματικά.</p>
προσαρμογή συμπεριφοράς εμφάνισης με χρήση των περιορισμών autolayout στο xcode 6
<p>δεν περιγράφετε κλίμακα για να ταιριάζει. περιγράφεις την εμφάνιση. (έχω επεξεργαστεί την ερώτησή σας σε αυτό το θέμα.) η υποβολή γίνεται όσο το δυνατόν μεγαλύτερη, διατηρώντας παράλληλα την αναλογία της και προσαρμόζοντας εξ ολοκλήρου μέσα στον γονέα της.</p><p>τέλος πάντων, μπορείτε να το κάνετε αυτό με αυτόματη διάταξη. μπορείτε να το κάνετε εξ ολοκλήρου στο ib από xcode 5.1. ας ξεκινήσουμε με μερικές προβολές:</p><p><img src="https://i.stack.imgur.com/hhdxr.png" alt="some views"></p><p>η ανοιχτή πράσινη όψη έχει αναλογία διαστάσεων 4: 1. η σκούρα πράσινη προβολή έχει αναλογία διαστάσεων 1: 4. πρόκειται να δημιουργήσω περιορισμούς έτσι ώστε η μπλε όψη να γεμίζει το πάνω μισό της οθόνης, η ροζ όψη να γεμίζει το κάτω μισό της οθόνης και κάθε πράσινη προβολή να επεκτείνεται όσο το δυνατόν περισσότερο, διατηρώντας παράλληλα τον λόγο διαστάσεων και προσαρμόζοντας την δοχείο.</p><p>κατ 'αρχάς, θα δημιουργήσω περιορισμούς και στις τέσσερις πλευρές της μπλε όψης. θα το περάσω στον κοντινότερο γείτονα σε κάθε άκρη, με απόσταση 0. φροντίζω να απενεργοποιήσω τα περιθώρια:</p><p><img src="https://i.stack.imgur.com/yo2jf.gif" alt="blue constraints"></p><p>σημειώστε ότι το i <strong> δεν ενημερώνει </strong> το πλαίσιο ακόμα. θεωρώ ότι είναι ευκολότερο να αφήνετε χώρο μεταξύ των απόψεων κατά τη δημιουργία περιορισμών και απλά να ορίσετε τις σταθερές στο 0 (ή οτιδήποτε άλλο) με το χέρι.</p><p>στη συνέχεια, κλίνω το αριστερό, το κάτω και το δεξί άκρο της ροζ εικόνας στον πλησιέστερο γείτονά της. δεν χρειάζεται να ρυθμίσω έναν ανώτατο περιορισμό edge επειδή η άνω άκρη του είναι ήδη περιορισμένη στο κάτω άκρο της μπλε όψης.</p><p><img src="https://i.stack.imgur.com/spins.gif" alt="pink constraints"></p><p>χρειάζομαι επίσης έναν περιορισμό ισοδύναμων μεταξύ των ροζ και μπλε απόψεων. αυτό θα τους κάνει να γεμίσουν το ήμισυ της οθόνης:</p><p><img src="https://i.stack.imgur.com/oelrv.gif" alt="enter image description here"></p><p>αν λέω στο xcode να ενημερώσει όλα τα πλαίσια τώρα, έχω αυτό:</p><p><img src="https://i.stack.imgur.com/9fbwl.png" alt="containers laid out"></p><p>έτσι, οι περιορισμοί που έχω δημιουργήσει μέχρι τώρα είναι σωστοί. ανεξάρτητα από αυτό και να αρχίσετε να εργάζεστε με την ανοιχτό πράσινη όψη.</p><p>η τοποθέτηση σε πτυχές της ανοιχτής πράσινης προβολής απαιτεί πέντε περιορισμούς:</p><ul> <li>απαιτούμενος λόγος αναλογίας διαστάσεων προτεραιότητας στην ανοιχτό πράσινη όψη. μπορείτε να δημιουργήσετε αυτόν τον περιορισμό σε xib ή storyboard με xcode 5.1 ή νεότερη έκδοση.</li> <li>ο περιορισμός της απαιτούμενης προτεραιότητας που περιορίζει το πλάτος της ανοιχτό πράσινης όψης να είναι μικρότερο ή ίσο με το πλάτος του δοχείου.</li> <li>ένας περιορισμός υψηλής προτεραιότητας που καθορίζει το πλάτος της ανοιχτής πράσινης όψης να είναι ίσο με το πλάτος του δοχείου.</li> <li>ο περιορισμός της απαιτούμενης προτεραιότητας που περιορίζει το ύψος της ανοιχτής πράσινης όψης να είναι μικρότερο ή ίσο με το ύψος του δοχείου.</li> <li>ένας περιορισμός υψηλής προτεραιότητας που θέτει το ύψος της ανοιχτής πράσινης όψης να είναι ίσο με το ύψος του δοχείου.</li> </ul><p>ας εξετάσουμε τους δύο περιορισμούς πλάτους. ο περιορισμός που δεν είναι ο ίδιος, είναι επαρκής για να καθορίσει το πλάτος της ανοιχτής πράσινης όψης. πολλά πλάτη θα ταιριάζουν με τον περιορισμό. δεδομένου ότι υπάρχει ασάφεια, το autolayout θα προσπαθήσει να επιλέξει μια λύση που ελαχιστοποιεί το σφάλμα στον άλλο περιορισμό (υψηλής προτεραιότητας αλλά όχι υποχρεωτικό). η ελαχιστοποίηση του σφάλματος σημαίνει ότι το πλάτος είναι όσο το δυνατόν πλησιέστερο στο πλάτος του κιβωτίου, ενώ δεν παραβιάζεται ο απαιτούμενος περιορισμός που δεν είναι μικρός ή ίσος.</p><p>το ίδιο συμβαίνει και με τον περιορισμό του ύψους. και επειδή απαιτείται επίσης ο περιορισμός της αναλογίας πλευρών, μπορεί να μεγιστοποιηθεί το μέγεθος του υποβιβασμού κατά μήκος ενός άξονα (εκτός αν ο περιέκτης έχει την ίδια αναλογία διαστάσεων με την υποέκθεση).</p><p>έτσι πρώτα δημιουργώ τον περιορισμό της αναλογίας διαστάσεων:</p><p><img src="https://i.stack.imgur.com/4ihow.gif" alt="top aspect"></p><p>στη συνέχεια, δημιουργώ ίσους περιορισμούς πλάτους και ύψους με το δοχείο:</p><p><img src="https://i.stack.imgur.com/vycag.gif" alt="top equal size"></p><p>πρέπει να επεξεργαστώ αυτούς τους περιορισμούς ώστε να είναι λιγότερο από-ή-ίσους περιορισμούς:</p><p><img src="https://i.stack.imgur.com/bc7rh.gif" alt="top less than or equal size"></p><p>στη συνέχεια πρέπει να δημιουργήσω ένα άλλο σύνολο ίσων περιορισμών πλάτους και ύψους με το δοχείο:</p><p><img src="https://i.stack.imgur.com/u9hkm.gif" alt="top equal size again"></p><p>και πρέπει να θέσω τους νέους αυτούς περιορισμούς λιγότερο από την απαιτούμενη προτεραιότητα:</p><p><img src="https://i.stack.imgur.com/i7dte.gif" alt="top equal not required"></p><p>τελικά, ζητήσατε να είναι κεντραρισμένο το υποπεριοχή στο δοχείο του, οπότε θα ρυθμίσω αυτούς τους περιορισμούς:</p><p><img src="https://i.stack.imgur.com/4dtr1.gif" alt="top centered"></p><p>τώρα, για να δοκιμάσετε, θα επιλέξω τον ελεγκτή προβολής και θα ζητήσω από το xcode να ενημερώσει όλα τα πλαίσια. αυτό έχω:</p><p><img src="https://i.stack.imgur.com/kmtoy.png" alt="incorrect top layout"></p><p>ωχ! το subview έχει επεκταθεί για να γεμίσει πλήρως το δοχείο του. αν το επιλέξω, μπορώ να δω ότι στην πραγματικότητα διατηρείται η αναλογία του, αλλά κάνει μια πτυχή - <strong> συμπληρώστε </strong> αντί για μια πτυχή - <strong> ταιριάζει </strong>.</p><p>το πρόβλημα είναι ότι σε έναν λιγότερο από ή ίσο περιορισμό, έχει σημασία ποια είναι η άποψη σε κάθε άκρο του περιορισμού, και το xcode έχει δημιουργήσει τον περιορισμό απέναντι από την προσδοκία μου. θα μπορούσα να επιλέξω καθέναν από τους δύο περιορισμούς και να αντιστρέψω το πρώτο και δεύτερο στοιχείο. αντ 'αυτού, θα επιλέξω μόνο το subview και θα αλλάξω τους περιορισμούς ώστε να είναι μεγαλύτερο από-ή-ίσο:</p><p><img src="https://i.stack.imgur.com/mh4xm.gif" alt="fix top constraints"></p><p>το xcode ενημερώνει τη διάταξη:</p><p><img src="https://i.stack.imgur.com/srvqg.png" alt="correct top layout"></p><p>τώρα κάνω όλα τα ίδια πράγματα με τη σκούρα πράσινη θέα στο κάτω μέρος. πρέπει να σιγουρευτώ ότι η αναλογία πλευρών είναι 1: 4 (το xcode το μείωσε με περίεργο τρόπο αφού δεν είχε περιορισμούς). δεν θα δείξω τα βήματα ξανά, αφού είναι τα ίδια. εδώ είναι το αποτέλεσμα:</p><p><img src="https://i.stack.imgur.com/kdj1r.png" alt="correct top and bottom layout"></p><p>τώρα μπορώ να το εκτελέσω στον προσομοιωτή iphone 4s, ο οποίος έχει διαφορετικό μέγεθος οθόνης από τον ib που χρησιμοποιείται και δοκιμή περιστροφής:</p><p><img src="https://i.stack.imgur.com/hpa6w.gif" alt="iphone 4s test"></p><p>και μπορώ να δοκιμάσω στο iphone 6 προσομοιωτή:</p><p><img src="https://i.stack.imgur.com/otbq9.gif" alt="iphone 6 test"></p><p>έχω ανεβάσει τον τελικό πίνακα ιστορικού μου στο <a href="https://gist.github.com/mayoff/d9320088ab4025c95e40">αυτό το gist</a> για την ευκολία σας.</p>
<p>rob, η απάντησή σου είναι φοβερή! γνωρίζω επίσης ότι αυτή η ερώτηση είναι συγκεκριμένα για την επίτευξη αυτού του στόχου με τη χρήση της αυτόματης διάταξης. ωστόσο, ακριβώς όπως μια αναφορά, θα ήθελα να δείξω πώς μπορεί να γίνει αυτό στον κώδικα. μπορείτε να ρυθμίσετε τις προβολές από πάνω και κάτω (μπλε και ροζ) ακριβώς όπως έδειξε ο rob. στη συνέχεια, δημιουργείτε μια προσαρμοσμένη <code>aspectfitview</code>:</p><p><strong> aspectfitview.h </strong>:</p><pre><code>#import &lt;uikit/uikit.h&gt; @interface aspectfitview : uiview @property (nonatomic, strong) uiview *childview; @end </code></pre><p><strong> aspectfitview.m </strong>:</p><pre><code>#import "aspectfitview.h" @implementation aspectfitview - (void)setchildview:(uiview *)childview { if (\_childview) { [\_childview removefromsuperview]; } \_childview = childview; [self addsubview:childview]; [self setneedslayout]; } - (void)layoutsubviews { [super layoutsubviews]; if (\_childview) { cgsize childsize = \_childview.frame.size; cgsize parentsize = self.frame.size; cgfloat aspectratioforheight = childsize.width / childsize.height; cgfloat aspectratioforwidth = childsize.height / childsize.width; if ((parentsize.height * aspectratioforheight) &gt; parentsize.height) { // whole height, adjust width cgfloat width = parentsize.width * aspectratioforwidth; \_childview.frame = cgrectmake((parentsize.width - width) / 2.0, 0, width, parentsize.height); } else { // whole width, adjust height cgfloat height = parentsize.height * aspectratioforheight; \_childview.frame = cgrectmake(0, (parentsize.height - height) / 2.0, parentsize.width, height); } } } @end </code></pre><p>στη συνέχεια, αλλάζετε την κλάση των μπλε και ροζ απόψεων στο storyboard για να είναι <code>aspectfitview</code>s. τέλος, ορίσατε δύο έξοδοι στον ελεγκτή <code>topaspectfitview</code> και <code>bottomaspectfitview</code> και ορίσατε το <code>childview</code>s στο <code>viewdidload</code>:</p><pre><code>- (void)viewdidload { [super viewdidload]; uiview *top = [[uiview alloc] initwithframe:cgrectmake(0, 0, 500, 100)]; top.backgroundcolor = [uicolor lightgraycolor]; uiview *bottom = [[uiview alloc] initwithframe:cgrectmake(0, 0, 100, 500)]; bottom.backgroundcolor = [uicolor greencolor]; \_topaspectfitview.childview = top; \_bottomaspectfitview.childview = bottom; } </code></pre><p>επομένως, δεν είναι δύσκολο να το κάνετε αυτό στον κώδικα και εξακολουθεί να είναι πολύ προσαρμόσιμο και λειτουργεί με μεταβλητού μεγέθους προβολές και διαφορετικούς λόγους αναλογίας.</p><p><strong> ενημέρωση ιουλίου 2015 </strong>: βρείτε μια εφαρμογή επίδειξης εδώ: <a href="https://github.com/jfahrenkrug/spwkaspectfitview">https://github.com/jfahrenkrug/spwkaspectfitview</a> </p>
<p>χρειαζόμουν μια λύση από την αποδεκτή απάντηση, αλλά εκτελείται από τον κώδικα. ο πιο κομψός τρόπος που έχω βρει χρησιμοποιεί <a href="https://github.com/masonry/masonry">πλαίσιο τοιχοποιίας</a> .</p><pre><code>#import "masonry.h" ... [view mas\_makeconstraints:^(masconstraintmaker *make) { make.width.equalto(view.mas\_height).multipliedby(aspectratio); make.size.lessthanorequalto(superview); make.size.equalto(superview).with.priorityhigh(); make.center.equalto(superview); }]; </code></pre>
<p><strong> αυτό είναι για το macos </strong></p><p>έχω πρόβλημα να χρησιμοποιήσω τον τρόπο του rob για να φτάσω στην εφαρμογή os x. αλλά το έκανα με άλλο τρόπο. αντί να χρησιμοποιώ πλάτος και ύψος, χρησιμοποίησα το κορυφαίο, το τελικό, το επάνω και το κάτω μέρος.</p><p>βασικά, προσθέστε δύο κύριους χώρους όπου η μία είναι&gt; = 0 @ 1000 απαιτούμενη προτεραιότητα και άλλη μία είναι = 0 @ 250 χαμηλής προτεραιότητας. πραγματοποιήστε τις ίδιες ρυθμίσεις στο τελικό, επάνω και κάτω κενό.</p><p>φυσικά, πρέπει να ρυθμίσετε το λόγο διαστάσεων και το κέντρο x και το κέντρο y.</p><p>και έπειτα δουλειά!</p><p> <a href="https://i.stack.imgur.com/mo1gs.png"><img src="https://i.stack.imgur.com/mo1gs.png" alt="enter image description here"></a> <a href="https://i.stack.imgur.com/owdwi.gif"><img src="https://i.stack.imgur.com/owdwi.gif" alt="enter image description here"></a> </p>
<p>βρήκα τον εαυτό μου να θέλει την εμφάνιση -<strong>fill</strong> συμπεριφορά έτσι ώστε ένα uiimageview να διατηρεί το δικό του λόγο διαστάσεων και να γεμίζει πλήρως την προβολή του δοχείου. με σύγχυση, το uiimageview μου έσπασε δύο βασικούς περιορισμούς ίσου πλάτους και ίσου ύψους (περιγράφονται στην απάντηση του rob) και απόδοση σε πλήρη ανάλυση.</p><p>η λύση ήταν απλά να ορίσετε την προτεραιότητα αντοχής συμπίεσης περιεχομένου uiimageview χαμηλότερη από την προτεραιότητα των περιορισμών ίσου πλάτους και ίσου ύψους:</p><p><img src="https://i.stack.imgur.com/lgjhr.png" alt="content compression resistance"></p>
<p>πρόκειται για μια εξαιρετική απάντηση της @ rob\_mayoff στην κωδικοκεντρική προσέγγιση, χρησιμοποιώντας αντικείμενα <code>nslayoutanchor</code> και μεταφερόμενα στο xamarin. για μένα, το <code>nslayoutanchor</code> και οι σχετικές κλάσεις έχουν κάνει το autolayout πολύ πιο εύκολο να προγραμματίσει:</p><pre><code>public class contentview : uiview { public contentview (uicolor fillcolor) { backgroundcolor = fillcolor; } } public class mycontroller : uiviewcontroller { public override void viewdidload () { base.viewdidload (); //starting point: var view = new contentview (uicolor.white); blueview = new contentview (uicolor.fromrgb (166, 200, 255)); view.addsubview (blueview); lightgreenview = new contentview (uicolor.fromrgb (200, 255, 220)); lightgreenview.frame = new cgrect (20, 40, 200, 60); view.addsubview (lightgreenview); pinkview = new contentview (uicolor.fromrgb (255, 204, 240)); view.addsubview (pinkview); greenview = new contentview (uicolor.green); greenview.frame = new cgrect (80, 20, 40, 200); pinkview.addsubview (greenview); //now start doing in code the things that @rob\_mayoff did in ib //make the blue view size up to its parent, but half the height blueview.translatesautoresizingmaskintoconstraints = false; var blueconstraints = new [] { blueview.leadinganchor.constraintequalto(view.layoutmarginsguide.leadinganchor), blueview.trailinganchor.constraintequalto(view.layoutmarginsguide.trailinganchor), blueview.topanchor.constraintequalto(view.layoutmarginsguide.topanchor), blueview.heightanchor.constraintequalto(view.layoutmarginsguide.heightanchor, (nfloat) 0.5) }; nslayoutconstraint.activateconstraints (blueconstraints); //make the pink view same size as blue view, and linked to bottom of blue view pinkview.translatesautoresizingmaskintoconstraints = false; var pinkconstraints = new [] { pinkview.leadinganchor.constraintequalto(blueview.leadinganchor), pinkview.trailinganchor.constraintequalto(blueview.trailinganchor), pinkview.heightanchor.constraintequalto(blueview.heightanchor), pinkview.topanchor.constraintequalto(blueview.bottomanchor) }; nslayoutconstraint.activateconstraints (pinkconstraints); //from here, address the aspect-fitting challenge: lightgreenview.translatesautoresizingmaskintoconstraints = false; //these are the must-fulfill constraints: var lightgreenconstraints = new [] { //aspect ratio of 1 : 5 nslayoutconstraint.create(lightgreenview, nslayoutattribute.height, nslayoutrelation.equal, lightgreenview, nslayoutattribute.width, (nfloat) 0.20, 0), //cannot be larger than parent's width or height lightgreenview.widthanchor.constraintlessthanorequalto(blueview.widthanchor), lightgreenview.heightanchor.constraintlessthanorequalto(blueview.heightanchor), //center in parent lightgreenview.centeryanchor.constraintequalto(blueview.centeryanchor), lightgreenview.centerxanchor.constraintequalto(blueview.centerxanchor) }; //must-fulfill foreach (var c in lightgreenconstraints) { c.priority = 1000; } nslayoutconstraint.activateconstraints (lightgreenconstraints); //low priority constraint to attempt to fill parent as much as possible (but lower priority than previous) var lightgreenlowpriorityconstraints = new [] { lightgreenview.widthanchor.constraintequalto(blueview.widthanchor), lightgreenview.heightanchor.constraintequalto(blueview.heightanchor) }; //lower priority foreach (var c in lightgreenlowpriorityconstraints) { c.priority = 750; } nslayoutconstraint.activateconstraints (lightgreenlowpriorityconstraints); //aspect-fit on the green view now greenview.translatesautoresizingmaskintoconstraints = false; var greenconstraints = new [] { //aspect ratio of 5:1 nslayoutconstraint.create(greenview, nslayoutattribute.height, nslayoutrelation.equal, greenview, nslayoutattribute.width, (nfloat) 5.0, 0), //cannot be larger than parent's width or height greenview.widthanchor.constraintlessthanorequalto(pinkview.widthanchor), greenview.heightanchor.constraintlessthanorequalto(pinkview.heightanchor), //center in parent greenview.centerxanchor.constraintequalto(pinkview.centerxanchor), greenview.centeryanchor.constraintequalto(pinkview.centeryanchor) }; //must fulfill foreach (var c in greenconstraints) { c.priority = 1000; } nslayoutconstraint.activateconstraints (greenconstraints); //low priority constraint to attempt to fill parent as much as possible (but lower priority than previous) var greenlowpriorityconstraints = new [] { greenview.widthanchor.constraintequalto(pinkview.widthanchor), greenview.heightanchor.constraintequalto(pinkview.heightanchor) }; //lower-priority than above foreach (var c in greenlowpriorityconstraints) { c.priority = 750; } nslayoutconstraint.activateconstraints (greenlowpriorityconstraints); this.view = view; view.layoutifneeded (); } } </code></pre>
<p>ίσως αυτή να είναι η συντομότερη απάντηση, με <a href="https://github.com/snapkit/masonry/">τοιχοποιία</a> , η οποία υποστηρίζει επίσης την εμφάνιση και την τέντωμα.</p><pre><code>typedef ns\_enum(nsinteger, contentmode) { contentmode\_aspectfit, contentmode\_aspectfill, contentmode\_stretch } // .... [containerview addsubview:subview]; [subview mas\_makeconstraints:^(masconstraintmaker *make) { if (contentmode == contentmode\_stretch) { make.edges.equalto(containerview); } else { make.center.equalto(containerview); make.edges.equalto(containerview).priorityhigh(); make.width.equalto(content.mas\_height).multipliedby(4.0 / 3); // the aspect ratio if (contentmode == contentmode\_aspectfit) { make.width.height.lessthanorequalto(containerview); } else { // contentmode == contentmode\_aspectfill make.width.height.greaterthanorequalto(containerview); } } }]; </code></pre>