Auto Layout: zwei views horizontal zentrieren (ohne diese in ein view zu packen)

  • macmoonshine schrieb:

    Unter iOS funktioniert deine Lösung allerdings bei der View-Rotation nicht optimal, wenn die Buttons breiter als die View-Breite im Hochformat ist. Dann stehen die Buttons entweder im Hochformat über den Rand hinaus, oder die Texte sind im Querformat gekürzt.
    Wenn von irgendeinem View die Breite größer ist als die View-Breit im Hochformat, funktionieren keine Constraints. (Genauer: Das errechnete Ergebnis ist nicht akzeptabel.) Das hat nichts mit dem konkretem Problem zu tun.

    Wenn in Kisuaheli die Buttons 8000 Pixel brauchen, funktioniert da auch nicht. Das hat aber auch nichts mit dem Problem zu tun.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    Michael schrieb:

    Und wo kommt da die Superviewbreite ins Spiel?

    Edit:
    Die Methode hat noch ein paar Parameter mehr. Welche Views, Attribute und Relation setzt du ein?
    Okay, wenn du nicht weißt, wie man Views und attribute bei den Constraints setzt, kann man natürlich auf den Gedanken kommen, dass du davon ausgehst, es ginge nicht. Ich kann dir einführende Literatur empfehlen. Vielleicht das hier:
    amazon.de/Mac-Programmierung-f…TF8&qid=1438348198&sr=1-2

    Wenn du einen konkreten Einwand hast. der mutmaßlich genau so falsch ist, wie deine bisherigen Einwände, dann äußere ihn. Sonst lass es bleiben.
    Es kann ja nicht sein, dass du falsch liegst, oder? Nun gut, ich war mal nicht faul und habe es praktisch umgesetzt:

    Quellcode

    1. CGFloat m = 0.5;
    2. CGFloat c = (-self.button1.frame.size.width - self.button2.frame.size.width - 8.0) *m;
    3. NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.button1 attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual
    4. toItem:self.window.contentView attribute:NSLayoutAttributeWidth multiplier:m constant:c];

    Wenn dir was an den Parametern nicht passt, sag es, aber bitte konkret. So, und nun rate mal, was in Zeile drei passiert.

    Quellcode

    1. An uncaught exception was raised
    2. *** +[NSLayoutConstraint constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:]: Invalid pairing of layout attributes
    Damit ist das Thema für mich durch.
  • macmoonshine schrieb:

    Amin Negm-Awad schrieb:

    Stellt sich nur die Frage, warum er bei Apple nicht gefallen ist.
    Ja, Layout-Constraints mit mehreren Variablen wären eine nette Sache, und der verwendete CSP-Solver sollte die auch beherrschen. Wahrscheinlich wollten sie die Klasse NSLayoutConstraint und den Interface-Builder einfach halten. ;)

    Amin Negm-Awad schrieb:

    Mutmaßlich haben die versucht, dass mit Swift zu implementieren
    Das ist meines Wissens in C++.
    Ich habe nicht mehrere Variablen, sondern eine Variable und mehrere Konstanten.

    Aber es gibt Fälle, da hätte man ganz gerne mehrere Variablen. Stimmt.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Michael schrieb:

    Amin Negm-Awad schrieb:

    Michael schrieb:

    Und wo kommt da die Superviewbreite ins Spiel?

    Edit:
    Die Methode hat noch ein paar Parameter mehr. Welche Views, Attribute und Relation setzt du ein?
    Okay, wenn du nicht weißt, wie man Views und attribute bei den Constraints setzt, kann man natürlich auf den Gedanken kommen, dass du davon ausgehst, es ginge nicht. Ich kann dir einführende Literatur empfehlen. Vielleicht das hier:amazon.de/Mac-Programmierung-f…TF8&qid=1438348198&sr=1-2

    Wenn du einen konkreten Einwand hast. der mutmaßlich genau so falsch ist, wie deine bisherigen Einwände, dann äußere ihn. Sonst lass es bleiben.
    Es kann ja nicht sein, dass du falsch liegst, oder? Nun gut, ich war mal nicht faul und habe es praktisch umgesetzt:

    Quellcode

    1. CGFloat m = 0.5;
    2. CGFloat c = (-self.button1.frame.size.width - self.button2.frame.size.width - 8.0) *m;
    3. NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.button1 attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual
    4. toItem:self.window.contentView attribute:NSLayoutAttributeWidth multiplier:m constant:c];
    Wenn dir was an den Parametern nicht passt, sag es, aber bitte konkret. So, und nun rate mal, was in Zeile drei passiert.

    Quellcode

    1. An uncaught exception was raised
    2. *** +[NSLayoutConstraint constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:]: Invalid pairing of layout attributes
    Damit ist das Thema für mich durch.
    Echt, man kann nicht das Leading abhängig machen vom superview? Das ist mal ein Ding …
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    Wenn von irgendeinem View die Breite größer ist als die View-Breit im Hochformat, funktionieren keine Constraints. (Genauer: Das errechnete Ergebnis ist nicht akzeptabel.) Das hat nichts mit dem konkretem Problem zu tun.
    Das Auto-Layout kann die Views ja stauchen; also beispielsweise durch Ellipsen die Texte kürzen. Bei kleinen View-Breiten kann das durchaus ein akzeptables Ergebnis sein. Bei Apps mit vielen Lokalisierungen kommt das auch nicht so selten vor.

    Amin Negm-Awad schrieb:

    Ich habe nicht mehrere Variablen, sondern eine Variable und mehrere Konstanten.
    Du berechnest ja zwei Werte, die Button-Breiten, um die Abstände zu erhalten. Wenn die Breiten tatsächlich zur Laufzeit konstant sind, ist das auch kein Problem. Wenn sich die Button-Breite ändern kann, musst du die Konstante des Constraints neu berechnen. Ein Constraint mit vier Variablen anstatt zwei wäre hier wesentlich eleganter, einfacher und flexibler.
    „Meine Komplikation hatte eine Komplikation.“
  • macmoonshine schrieb:

    Amin Negm-Awad schrieb:

    Wenn von irgendeinem View die Breite größer ist als die View-Breit im Hochformat, funktionieren keine Constraints. (Genauer: Das errechnete Ergebnis ist nicht akzeptabel.) Das hat nichts mit dem konkretem Problem zu tun.
    Das Auto-Layout kann die Views ja stauchen; also beispielsweise durch Ellipsen die Texte kürzen. Bei kleinen View-Breiten kann das durchaus ein akzeptables Ergebnis sein. Bei Apps mit vielen Lokalisierungen kommt das auch nicht so selten vor.

    Amin Negm-Awad schrieb:

    Ich habe nicht mehrere Variablen, sondern eine Variable und mehrere Konstanten.
    Du berechnest ja zwei Werte, die Button-Breiten, um die Abstände zu erhalten. Wenn die Breiten tatsächlich zur Laufzeit konstant sind, ist das auch kein Problem. Wenn sich die Button-Breite ändern kann, musst du die Konstante des Constraints neu berechnen. Ein Constraint mit vier Variablen anstatt zwei wäre hier wesentlich eleganter, einfacher und flexibler.
    Dass ich die Buttongröße zur Laufzeit ändere, ist aber eher schon selten. Das würde aber aus dem Code heraus erfolgen, so dass es ja auch kein Problem wäre, die Berechnung neu durchzuführen.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    BTW: Es kann immer sein, dass ich falsch liege. Deshalb hatte ich ja gefragt, warum das nicht gehen soll. Nur bekam ich darauf Gründe genannt, die falsch waren, wo ich also richtig lag.
    Aus meiner Sicht sollte deine Lösung mit festen Button-Größen funktionieren. Constraints über berechnete Größen von Views zu formulieren, finde ich allerdings nicht so elegant, weswegen ich hier eher doch einen Hilfsview bevorzugen würde.
    „Meine Komplikation hatte eine Komplikation.“
  • Nein, das wurde nicht mehrfach gesagt. Es wurde mehrfach gesagt, dass man das nicht in die Constraint-Form bringen kann. Und es wurde gesagt, dass das nicht mit Lokalisierung geht. Und es wurde gesagt, dass es nicht bei Änderungen der Fenstergröße geht. Und es wurde gesagt, dass es nicht bei Drehung des Devices geht.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • macmoonshine schrieb:

    Amin Negm-Awad schrieb:

    BTW: Es kann immer sein, dass ich falsch liege. Deshalb hatte ich ja gefragt, warum das nicht gehen soll. Nur bekam ich darauf Gründe genannt, die falsch waren, wo ich also richtig lag.
    Aus meiner Sicht sollte deine Lösung mit festen Button-Größen funktionieren. Constraints über berechnete Größen von Views zu formulieren, finde ich allerdings nicht so elegant, weswegen ich hier eher doch einen Hilfsview bevorzugen würde.
    Ich würde in jedem Falle einen Hilfsview nehmen, hatte ich schon erwähnt. Die Nachteile wiegen für mich jedenfalls bei so einfachen Fällen überhaupt nicht. Ich habe auch keine Ahnung, warum Gritsch das nicht will.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    Es wurde mehrfach gesagt, dass man das nicht in die Constraint-Form bringen kann.
    Theoretisch falsch, praktisch richtig. Nur alle Theorie hilft mir nicht, wenn mein Programm abschmiert.

    Amin Negm-Awad schrieb:

    Und es wurde gesagt, dass das nicht mit Lokalisierung geht.
    Das bezog sich vor allem auf die Aussage, dass die Buttons eine konstante Breite haben. Gut, da kann man drum rum programmieren. Insofern ist die Aussage unpräzise, aber nicht grundsätzlich falsch.

    Um mal auf den Ursprung zurück zu kommen. Gesucht war eine einfache Lösung des Problems ohne die Buttons in einen extra View zu packen. Selbst wenn es im Code gehen würde, wäre der Aufwand (Outlets, Berechnung durchführen, Constraint erzeugen und setzen deutlich höher, als einen extra View zu verwenden. Aber da sind wir uns ja einig.
  • Ah,

    Michael schrieb:

    Leider gibt es keine Möglichkeit (ich sehe jedenfalls keine), so einen Constraint zu formulieren, der zwei Abstände zwischen verschiedenen Elementen gleich groß hält. Das wäre dann ja ein Constraint, der zwei andere Constraints beeinflusst.

    macmoonshine schrieb:

    Du kannst keine Constraints auf die Breite von Randabständen setzen, sondern nur auf die Positionen der Rändern.

    Michael schrieb:

    Das ist uns allen klar. Nur jetzt übersetze diese Formel mal in einen oder mehrere NSLayoutContraint. Da wird's dann eng.
    Heißt also: Das geht zwar theoretisch, aber praktisch nicht.

    Verstehe.

    Nun, wenn die Autolayout-engine mit einer Kombination von Constraints unzufrieden ist, weiß sich ja der erfahrene Programmierer zu helfen: Er nimmt eine andere Kombination, die inhaltlich äquivalent ist und das Ding nicht meckern lässt. Zum Beispiel:


    Quellcode

    1. NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:self.first attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.first.superview attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:-36.0];
    2. [self.window.contentView addConstraint:constraint1];
    Also bei mir funktioniert das 1A. Aber wenn du es nicht hinbekommst, ist es natürlich nicht möglich …

    Und – UI! – das geht sogar im IB. (Ohne Lokalisierung)

    Wieso die Erzeugung von Constarint im Code "drum herum programmieren ist", bleibt wohl dein persönliches Geheimnis. Ich dachte, die API hätte einen Sinn.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Amin Negm-Awad ()

  • h, es müsste sogar mit Lokalisierung im Interface Builder gehen, wenn man statt CenterX einfach Right bzw. Left nimmt.
    Dateien
    • ffff.zip

      (30,35 kB, 163 mal heruntergeladen, zuletzt: )
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Amin Negm-Awad ()

  • Amin Negm-Awad schrieb:

    Also bei mir funktioniert das 1A. Aber wenn du es nicht hinbekommst, ist es natürlich nicht möglich …
    Ist es meine Aufgabe, deine Aussagen hier mit praktischen Beispielen zu belegen? Lass mal überlegen: nein. Das hättest du alles auch schon 34 Beiträge vorher machen können.


    Amin Negm-Awad schrieb:

    Wieso die Erzeugung von Constarint im Code "drum herum programmieren ist", bleibt wohl dein persönliches Geheimnis.
    Ich entschuldige mich dafür, dass meine Formulierungen nicht dem wissenschaftlichen Standard entsprechen und für dich nicht verständlich sind. Tut mir echt leid.


    Amin Negm-Awad schrieb:

    h, es müsste sogar mit Lokalisierung im Interface Builder gehen, wenn man statt CenterX einfach Right bzw. Left nimmt.
    Aber nur, wenn dir egal ist, dass der linke und rechte Abstand zum Superview nicht gleich groß ist. Dein Beispiel richtet die Buttons nur am Zentrum aus, es zentriert sie nicht im Superview. Dazu müsstest du entweder den Buttons noch sagen, dass sie gleich breit sein sollen oder zur Laufzeit die Konstante anpassen.
  • Nein, es ist aber deine Aufgabe – wenn man hier überhaupt eine hat –, deine Ansichten zu belegen. Und von den zahlreichen Einwänden haben sich bisher alle als fehlerhaft herausgestellt.

    Es geht auch nicht um eine Formulierung, sondern um den Inhalt. Das ist kein "drum herum programmieren". Sondern genau so wie gedacht: Es gibt eine API, damit man diese benutzt. Und es gibt sogar eine API (ASCII-Art), die es überhaupt nur dazu gibt, damit man diese benutzt. Es ist also genau so wie gedacht. Das ist das Gegenteil von "drum herum programmieren".

    Und ja, wenn du verschieden große Buttons hast, die aber mittig über die Gesamtbreite stehen sollen (was immerhin gegen die UI-Guidelines verstößt), dan musst du tatsächlich für Lokalisierung eine Berechnung durchführen und ein Constraint im Code setzen. Genau so, wie das gedacht ist.

    Das klingt deutlich anders als "Geht nicht".
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?