web-dev-qa-db-fra.com

Comprendre le multiplicateur dans la disposition automatique pour utiliser le positionnement relatif

J'essaie de comprendre comment on peut utiliser la disposition automatique pour positionner les éléments par rapport à d'autres vues en pourcentage.

Par exemple, j'ai récemment appris que vous pouvez spécifier que le bas d'une vue doit être supérieur de 4% au bas de sa vue d'ensemble en utilisant ceci:

self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 0.96, constant: 0))

Cela a du sens pour moi car un multiplicateur de 1 l'alignerait tout en bas de la vue, vous pouvez donc diminuer ce montant de 4% en modifiant le multiplicateur à 0,96.

Mais comment faire de même dans l'autre sens? Vous souhaitez spécifier que le haut d'une étiquette doit commencer à 4% du haut de la vue d'ensemble. Si vous utilisez cette même ligne mais changez les attributs en .Top, cela signifie qu'il serait 4% plus élevé que le haut de la vue d'ensemble (mais en réalité, il ne le fait pas disparaître de l'écran). Vous ne pouvez pas avoir un multiplicateur négatif, je ne pense pas, et je ne crois pas qu'une valeur supérieure à 1 fasse quoi que ce soit lorsque la constante est 0. Alors, comment pouvez-vous configurer cela?

J'ai la même question pour l'implémentation du début et de la fin. Le suivi est facile. Si vous le souhaitez à 10% de la droite:

self.view.addConstraint(NSLayoutConstraint(item: label, attribute: .Trailing, relatedBy: .Equal, toItem: self.view, attribute: .Trailing, multiplier: 0.9, constant: 0))

Cela a du sens parce que vous le composez à 0,1 ou 10% au lieu de l'aligner complètement à 1,0. Mais comment faites-vous la même chose pour diriger? J'ai pensé que vous pourriez peut-être définir le début de l'étiquette par rapport à la fin de la vue, puis définir le multiplicateur sur 0,1. Dans mon esprit, cela signifierait que l'étiquette commencerait à l'extrême droite mais serait recomposée à 90%, obtenant ainsi les 10% souhaités à partir de la gauche. Mais ce n'est pas le cas, je ne sais pas pourquoi.

Pouvez-vous expliquer comment cela fonctionne, comment utiliser correctement le multiplicateur pour obtenir ces dispositions relatives?

Pour vous faciliter la tâche, supposons que vous souhaitiez créer une étiquette dont les haut et bas 10% de la hauteur de la vue d'ensemble, et 10% en fin et en tête de la largeur de la vue d'ensemble. Sur un iPhone en mode portrait, il y aura plus de rembourrage au-dessus et en dessous de l'étiquette qu'il n'y a de rembourrage à gauche et à droite, comme ça (oui, il est dessiné à l'échelle):
enter image description here

Mais disons que sur l'iPad ça va être montré dans une vue qui est un carré parfait. Par conséquent, le rembourrage sera de la même quantité tout autour, comme ceci:
enter image description here

La question est de savoir comment définir de telles contraintes comme étant dynamiques en valeur, au lieu de définir une valeur fixe pour une constante. Je sais déjà comment faire en bas et en queue, mais en haut et en tête m'a déconcerté. J'espère comprendre comment utiliser le multiplicateur pour faire des mises en page plus avancées, par exemple, en spécifiant que le haut d'une étiquette doit se situer à 10% sous le bas d'une autre étiquette, au lieu de le définir sur une constante fixe.

29
Jordan H

Il y a plusieurs façons de procéder. Dans le cas le plus simple, vous l'avez presque déjà: si vous voulez que les limites horizontales soient à 10% et 90%, vous devez spécifier les deux contraintes par rapport au bord de fuite du superview - donc Subview.Trailing se verrouille sur Superview.Trailing avec un multiplicateur de 0.9, comme vous dites, mais Subview.Leading se verrouille également sur Superview.Trailing, juste avec un multiplicateur de 0.1:

enter image description here

(et de même pour le haut/bas)

D'un autre côté, le cas que vous mentionnez à la fin est un peu plus compliqué: "spécifier le haut d'une étiquette doit se trouver à 10% sous le bas d'une autre étiquette". Pour cela, vous ne pourrez probablement pas utiliser des encarts à pourcentage fixe comme le cas précédent. Au lieu de cela, vous pouvez créer une vue d'espacement invisible entre eux: ajoutez une contrainte avec Spacer.Height = 0.1 * Superview.Height, puis fixez-le entre les deux étiquettes. (Vous pouvez également gérer le cas précédent avec ces vues d'espacement, mais pour ce cas, ce n'est pas vraiment nécessaire.)

27
Archaeopterasa

À mon avis, "Vous ne pouvez pas avoir un multiplicateur négatif, je ne pense pas, et je ne crois pas qu'une valeur supérieure à 1 fasse quoi que ce soit lorsque la constante est 0" a exposé votre écart de compréhension.

La règle sous le capot n'est qu'une équation linéaire:

FirstItem.Attribute1 = (SecondItem.Attribute2 * Multiplier) + Constant

Tous mesurés en points. Comme vous le voyez, le multiplicateur (une propriété de NSLayoutConstraint) n'est pas le multiplicateur de constante. Suivez l'équation, ce que vous ne comprenez pas sera clair.

Quant à votre exemple spécifique, @Archaeopterasa a présenté une excellente solution, une autre est illustrée ci-dessous:

Sur la base du fait que vous savez comment faire en bas et en fin, je suppose que vous avez fait ces deux. Ajoutez ensuite deux autres contraintes, l'effet sera ce que vous voulez: set label's width to 80% superview's widthset label's height to 80% superview's height

Enfin, si vous souhaitez spécifier le haut d'une étiquette à 10% sous le bas d'une autre étiquette, il semble que vous ne pouvez pas l'implémenter sans écrire une ligne de code. Vous devez utiliser du code pour définir la constante de l'objet NSLayoutConstraint connectant le FirstItem et le SecondItem après que la hauteur de la vue d'ensemble est connue dans l'exécution.

Tout d'abord, contrôlez le glissement d'une étiquette à l'autre et choisissez "Espacement vertical" (ou vous pouvez le faire d'autres manières).

Deuxièmement, une prise de référence est nécessaire:

@IBOutlet weak var tenPercentOfSuperview: NSLayoutConstraint!

Ensuite, faites-le à un endroit approprié (par exemple, dans viewDidLoad ())

let heightOfSuperview = self.view.bounds.height
tenPercentOfSuperview.constant = heightOfSuperview * 0.1

Tout va bien maintenant.

Si vous souhaitez en savoir plus sur ce sujet, le document d'Apple est recommandé: https://developer.Apple.com/library/ios/recipes/xcode_help-IB_auto_layout/chapters/EditingConstraintAttributesintheAttributesInspector.html

8
fujianjin6471

Ici se trouve le

INCROYABLEMENT SIMPLE

façon de le faire.

Ajoutez simplement des vues "d'aide" ou de "mesure":

Les vues "aide au calcul" sont jaunes dans l'exemple.

La technique générale est si simple et évidente - elle n'a besoin d'aucune explication, vous pouvez l'obtenir à partir de l'image.

C'est une de ces "éléphants dans la pièce" dont ils "ne vous apprennent pas" sur iOS. Mais il est utilisé en permanence dans toutes les mises en page.

(En effet, Apple aurait dû créer une "mesure" spéciale de la sous-classe UIView exactement à cette fin - et en effet, de nombreuses grandes équipes le font, avec les caractéristiques évidentes.)

enter image description here

L'icône d'avis n ° 1 est centrée sur l'extrémité droite de la vue d'aide "View 1/4".

L'icône d'avis n ° 3 est centrée sur l'extrémité gauche de la vue d'aide "View 3/4".

Vous avez terminé, prenez un Chardonnay.

Idéalement, dans les vues d'aide, il suffit de régler le multiplicateur sur tout ce que vous voulez, selon la sensation souhaitée. Il est incroyablement facile de modifier ensuite ceux de votre code, d'utiliser IBInspectable, d'animer , et ainsi de suite ...

enter image description here

4
Fattie