What is auto layout & constraints in iOS design?

Mestring af Auto Layout & Constraints i iOS

17/06/2022

Rating: 4.06 (9413 votes)

I den dynamiske verden af iOS app-udvikling er det afgørende at skabe layouts, der problemfrit tilpasser sig forskellige skærmstørrelser og orienteringer. Her kommer Auto Layout og constraints ind i billedet – kraftfulde værktøjer, der hjælper udviklere med at designe responsive brugerflader til iPhones og iPads. I denne dybdegående guide vil vi dykke ned i Auto Layouts og constraints' verden, udforske deres grundlæggende principper, brug og give dig praktiske eksempler til at bygge fleksible og adaptive layouts, der imponerer dine brugere, uanset hvilken enhed de anvender.

What is auto layout & constraints in iOS design?
Auto Layout and constraints form the backbone of responsive iOS design. By understanding the basics of constraints and embracing the power of trait variations, you can build interfaces that gracefully adapt to the ever-evolving iOS device landscape.
Indholdsfortegnelse

Forstå Grundlaget for Auto Layout

Hvad er Auto Layout?

Auto Layout er et avanceret layouts-system, leveret af Apple, der gør det muligt for udviklere at skabe brugerflader, som automatisk tilpasser sig forskellige skærmstørrelser, opløsninger og orienteringer. Det er en afgørende komponent i opbygningen af iOS-apps, der ser fantastiske ud på alle enheder, lige fra den mindste iPhone SE til den største iPad Pro. Med Auto Layout definerer du et sæt regler, også kendt som constraints, der dikterer, hvordan de forskellige elementer i din brugerflade forholder sig til hinanden og til den overordnede visning, de indeholder. I stedet for at angive faste pixelværdier for placering og størrelse, beskriver du relationer, som "denne knap skal være 20 punkter fra toppen af skærmen og midtstillet horisontalt". Auto Layout løser derefter disse relationer dynamisk for at bestemme den optimale placering og størrelse for hvert element baseret på enhedens aktuelle egenskaber.

Hvorfor Bruge Auto Layout?

Dage med at skabe separate layouts for hver enkelt enhed er forbi. Auto Layout bringer en hidtil uset effektivitet til designprocessen ved at give udviklere mulighed for at skabe layouts, der tilpasser sig og justerer dynamisk. Forestil dig en situation, hvor en ny iPhone-model med en anderledes skærmstørrelse lanceres, eller en bruger roterer deres enhed fra stående til liggende orientering. Uden Auto Layout ville dine brugerfladeelementer sandsynligvis blive forvrænget, overlappe eller forsvinde fra skærmen. Auto Layout sikrer, at dine brugerfladeelementer bevarer deres relative positioner, proportioner og læsbarhed, hvilket giver en konsistent og professionel brugeroplevelse på tværs af hele Apples økosystem af iOS-enheder. Det reducerer den tid og indsats, der kræves for at vedligeholde appens udseende, da ændringer kan håndteres centralt via constraints i stedet for at skulle justeres manuelt på tværs af flere layout-filer.

Kom i Gang med Constraints

Constraints 101: Hjertet af Dit Layout

I hjertet af Auto Layout er constraints – regler, der definerer forholdet mellem brugerfladeelementer. Disse constraints anvendes på attributter såsom bredde, højde, positioner og afstand. Constraints fungerer ved at specificere justeringen og afstanden mellem elementerne, hvilket skaber et system af ligninger, som Auto Layout løser for at bestemme det passende layout for den aktuelle enhed. Tænk på det som et avanceret puslespil, hvor hvert stykke (dit UI-element) har specifikke krav til, hvordan det skal forholde sig til de andre stykker og rammen (din visning). Når alle regler er defineret, finder Auto Layout den eneste mulige løsning for at arrangere elementerne.

Typer af Constraints

For at bygge robuste og fleksible layouts er det vigtigt at forstå de forskellige typer af constraints, du kan anvende:

  • Positions-Constraints: Disse definerer et elements vandrette og lodrette position inden for dets container. Eksempler inkluderer leading (venstre kant), trailing (højre kant), top (topkant) og bottom (bundkant) constraints. Du kan også centrere elementer vandret eller lodret.
  • Dimensions-Constraints: Disse styrer et elements bredde og højde. Du kan indstille eksplicitte dimensioner (f.eks. bredde = 100 punkter) eller bruge constraints, der afhænger af elementets intrinsiske indholdsstørrelse (f.eks. en knaps bredde er dikteret af teksten indeni).
  • Aspektforholds-Constraints: At opretholde aspektforholdet for et element, såsom et billede eller en videoafspiller, er afgørende for at undgå forvrængning. Aspektforholds-constraints sikrer, at elementets proportioner forbliver konstante under layoutændringer, uanset dets faktiske dimensioner på skærmen.

Tilføjelse af Constraints i Interface Builder

Xcode's Interface Builder er et visuelt designværktøj, der gør det nemt at tilføje og administrere constraints uden at skrive kode. Lad os gennemgå processen:

  1. Vælg Elementet: Klik på det brugerfladeelement (f.eks. en knap, et tekstfelt), du vil tilføje constraints til, inden for din storyboard- eller XIB-fil.
  2. Tilføj Constraints: Nederst i Interface Builder-vinduet finder du en række ikoner. Klik på "Add New Constraints"-knappen (den ligner et slipsfly eller en firkant med T-formede linjer).
  3. Konfigurer Constraints: En pop-up menu vises, hvor du kan definere de constraints, du vil anvende. Du kan indstille afstande til elementets superview (den visning, det er indeholdt i) eller til andre elementer. Du kan også indstille bredde- og højde-constraints, justerings-constraints (f.eks. centrer horisontalt i containeren) og aspektforhold.
  4. Opdater Rammer: Når du har tilføjet constraints, kan du se, at elementet muligvis ikke flytter sig med det samme. Klik på "Update Frames" (ikonet ligner to pile, der danner en cirkel) for at få Interface Builder til at anvende de nye constraints og opdatere elementets visuelle placering.

Interface Builder giver også visuelle indikatorer for manglende eller modstridende constraints, hvilket hjælper dig med at debugge layoutproblemer hurtigt. Blå linjer indikerer, at et constraint er fuldt defineret og fungerer korrekt, mens røde eller gule linjer ofte indikerer problemer, der skal løses.

Tilføjelse af Constraints Programmatisk

Selvom Interface Builder er fantastisk til at visualisere constraints, kan du også tilføje dem direkte i kode. Denne tilgang giver mere kontrol og er ofte nødvendig, når du håndterer komplekse eller dynamisk genererede layouts. Det er også foretrukket af mange udviklere, der foretrækker at have al layoutlogik i kodebasen.

Her er et eksempel på Swift-kode, der programmatisk tilføjer constraints:

// Antager at du har to UIViews kaldet viewA og viewB // Vigtigt: Sæt translatesAutoresizingMaskIntoConstraints til false for views, du tilføjer constraints til programmatisk viewA.translatesAutoresizingMaskIntoConstraints = false viewB.translatesAutoresizingMaskIntoConstraints = false let leadingConstraint = NSLayoutConstraint(item: viewA, attribute: .leading, relatedBy: .equal, toItem: viewB, attribute: .leading, multiplier: 1.0, constant: 20.0) let topConstraint = NSLayoutConstraint(item: viewA, attribute: .top, relatedBy: .equal, toItem: viewB, attribute: .bottom, multiplier: 1.0, constant: 10.0) let widthConstraint = NSLayoutConstraint(item: viewA, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 150.0) let heightConstraint = NSLayoutConstraint(item: viewA, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 80.0) // Aktiver constraints NSLayoutConstraint.activate([leadingConstraint, topConstraint, widthConstraint, heightConstraint]) 

I eksemplet ovenfor:

  • translatesAutoresizingMaskIntoConstraints = false: Dette er afgørende. Standardværdien er true, hvilket automatisk genererer constraints baseret på viewets autoresizing mask. Hvis du vil bruge Auto Layout programmatisk, skal du deaktivere denne adfærd.
  • NSLayoutConstraint(item:attribute:relatedBy:toItem:attribute:multiplier:constant:): Dette er initialisatoren for et constraint.
    • item: Det første element i relationen.
    • attribute: Attributten på det første element (f.eks. .leading, .top, .width).
    • relatedBy: Relationstypen (f.eks. .equal, .greaterThanOrEqual, .lessThanOrEqual).
    • toItem: Det andet element i relationen (kan være nil for dimensionelle constraints, der refererer til sig selv, som bredde og højde).
    • attribute: Attributten på det andet element.
    • multiplier: En multiplikator, der anvendes på det andet elements attribut.
    • constant: En konstant forskydning eller værdi.
  • NSLayoutConstraint.activate([...]): Dette er den foretrukne måde at aktivere flere constraints på. Det er mere effektivt end at aktivere dem individuelt.

Programmatisk tilgang er især nyttig i komplekse scenarier, såsom at generere dynamiske visninger i en scroll-visning, oprette brugerdefinerede overgange eller når du har brug for præcis kontrol over hver enkelt constraint.

Bygning af Adaptive Brugerflader

At skabe en brugerflade, der ser godt ud på alle enheder, kræver mere end blot at tilføje constraints. Det handler om at tænke adaptivt, og her spiller Størrelsesklasser og Trait-variationer en central rolle.

Størrelsesklasser (Size Classes)

Størrelsesklasser er Apples måde at kategorisere enheder baseret på deres skærmstørrelse og orientering på et abstrakt niveau. Denne klassifikation hjælper designere og udviklere med at skabe layouts, der tilpasser sig forskellige skærmstørrelser uden at skabe separate interfaces for hver specifik enhed. De to primære størrelsesklasser er:

  • Regular: Angiver et stort eller udvidet rum (f.eks. en iPad i enhver orientering, eller en iPhone i liggende orientering).
  • Compact: Angiver et begrænset eller komprimeret rum (f.eks. en iPhone i stående orientering).

Disse klasser anvendes både horisontalt (horizontalSizeClass) og vertikalt (verticalSizeClass), hvilket giver fire mulige kombinationer (Regular-Regular, Regular-Compact, Compact-Regular, Compact-Compact). En iPhone i stående tilstand er f.eks. Compact-Width Regular-Height, mens en iPad i enhver orientering er Regular-Width Regular-Height.

Trait-Variationer (Trait Variations)

Inden for størrelsesklasser definerer traits specifikke attributter for en enheds miljø, såsom liggende eller stående orientering, brugerflade-idiom (iPhone eller iPad), og skærmens skaleringsfaktor. Trait-samlingen (UITraitCollection) indeholder alle disse egenskaber. Ved at kombinere størrelsesklasser og traits kan du skabe yderst adaptable layouts, der imødekommer forskellige scenarier. For eksempel kan du designe en detailvisning, der viser produkter i en kolonne på en iPhone (Compact-Width) men i et gitter på en iPad (Regular-Width).

Adaptive Constraints i Praksis

For at skabe adaptive layouts kan du udnytte trait-variationer i kombination med constraints. Ved at definere forskellige constraints baseret på størrelsesklasser og traits kan du sikre, at dine brugerfladeelementer omarrangeres og tilpasses passende for hver enhedskonfiguration. Dette gøres typisk ved at override traitCollectionDidChange(_:) metoden i din UIViewController:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) // Tjek om den horisontale størrelsesklasse har ændret sig if traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass { if traitCollection.horizontalSizeClass == .compact { // Anvend constraints, der er egnede til kompakt bredde (f.eks. iPhone i stående) // Eksempel: Skift layout fra en række til en kolonne // Deaktiver række-constraints, aktiver kolonne-constraints leadingConstraintCompact.isActive = true trailingConstraintCompact.isActive = true topConstraintCompact.isActive = true bottomConstraintCompact.isActive = true leadingConstraintRegular.isActive = false trailingConstraintRegular.isActive = false topConstraintRegular.isActive = false bottomConstraintRegular.isActive = false } else if traitCollection.horizontalSizeClass == .regular { // Anvend constraints, der er egnede til regulær bredde (f.eks. iPad, iPhone i liggende) // Eksempel: Skift layout fra en kolonne til en række // Deaktiver kolonne-constraints, aktiver række-constraints leadingConstraintCompact.isActive = false trailingConstraintCompact.isActive = false topConstraintCompact.isActive = false bottomConstraintCompact.isActive = false leadingConstraintRegular.isActive = true trailingConstraintRegular.isActive = true topConstraintRegular.isActive = true bottomConstraintRegular.isActive = true } // Tving layoutopdatering view.setNeedsLayout() view.layoutIfNeeded() } } 

I dette eksempel antages det, at du har to sæt constraints (f.eks. leadingConstraintCompact og leadingConstraintRegular), som du skifter mellem baseret på den horisontale størrelsesklasse. Dette giver dig utrolig fleksibilitet til at skræddersy din brugerflade til forskellige enhedskonfigurationer, hvilket sikrer en optimal brugeroplevelse under alle forhold.

Why is adaptive design important for iOS devices?
Adaptive design allows you to have more control over how your layout appears across different iOS devices, regardless of their screen size. With a variety of screen sizes available for iOS devices, adaptive design ensures that your app looks great on all of them.

Håndtering af Dynamisk Indhold

I virkelige apps ændrer indholdet sig ofte dynamisk – tekstlængder varierer, billeder indlæses, og elementer vises eller skjules. Auto Layout har mekanismer til at håndtere dette elegant.

Content Hugging og Compression Resistance Prioriteter

Disse to prioriteter bestemmer, hvordan et brugerfladeelement modstår at blive mindre eller udvide sig for at fylde tilgængelig plads. De er afgørende, når du håndterer dynamisk indhold, såsom labels med varierende tekstlængder eller billeder med forskellige størrelser. Prioriteterne spænder fra 1 til 1000, hvor 1000 er den højeste prioritet.

  • Content Hugging Priority (CHP): Bestemmer, hvor stærkt et element modstår at blive større end dets intrinsiske indholdsstørrelse. Et element med høj CHP vil "kramme" sit indhold tæt og ikke udvide sig unødvendigt. Hvis du har to labels side om side, og den ene skal have lov til at udvide sig mere end den anden, vil den label, der skal forblive tæt på sit indhold, have en højere CHP.
  • Compression Resistance Priority (CRP): Bestemmer, hvor stærkt et element modstår at blive komprimeret eller skrumpet ind, så det bliver mindre end dets intrinsiske indholdsstørrelse. Et element med høj CRP vil kæmpe for at bevare sin fulde størrelse, selv når pladsen er begrænset. Hvis du har en label med vigtig tekst, der ikke må afkortes, skal den have en høj CRP.

For eksempel vil en label med høj content hugging-prioritet forsøge at opretholde sin intrinsiske indholdsstørrelse, mens en label med høj kompressionsmodstandsprioritet vil modstå at blive komprimeret, når pladsen er begrænset. Ved at justere disse prioriteter kan du styre, hvilke elementer der skal give efter, og hvilke der skal bevare deres størrelse, når Auto Layout skal løse tvetydigheder i layoutet.

Dynamisk Opdatering af Constraints

Efterhånden som din app's indhold ændrer sig dynamisk, skal du muligvis opdatere constraints for at imødekomme ændringerne. For at gøre dette skal du oprette outlets for dine constraints i kode og ændre deres konstantværdier efter behov. Dette er typisk nødvendigt, når du ændrer tekst i en label, skjuler eller viser visninger, eller når data fra et netværk ændrer layoutkravene.

@IBOutlet var widthConstraint: NSLayoutConstraint! @IBOutlet var topConstraint: NSLayoutConstraint! // Opdater bredde-constraint-konstanten dynamisk func updateLayoutForNewContent(newWidthValue: CGFloat, newTopOffset: CGFloat) { widthConstraint.constant = newWidthValue topConstraint.constant = newTopOffset // Kald dette for at tvinge layoutopdatering // Dette beder viewet om at genberegne dets layout baseret på de opdaterede constraints view.setNeedsLayout() // Marker viewet som værende i behov for layout view.layoutIfNeeded() // Tving en øjeblikkelig layoutopdatering } 

view.setNeedsLayout() markerer viewet som "beskidt" og indikerer, at dets layout skal genberegnes ved næste opdateringscyklus. view.layoutIfNeeded() tvinger en øjeblikkelig layoutopdatering, hvis der er udestående layoutkrav. Det er vigtigt at kalde layoutIfNeeded(), når du foretager øjeblikkelige ændringer, der skal reflekteres i brugerfladen med det samme, især hvis du animerer layoutændringer.

Sammenligning: Interface Builder vs. Programmatisk Constraints

Valget mellem at bruge Interface Builder (storyboards/XIBs) og programmatisk kode til at definere Auto Layout constraints afhænger ofte af personlige præferencer, projektets kompleksitet og teamets arbejdsgange. Begge tilgange har deres fordele og ulemper.

FunktionInterface Builder (Visuelt)Programmatisk (Kode)
Visuel RepræsentationFremragende. Du ser layoutet direkte og kan nemt trække, slippe og justere elementer.Ingen direkte visuel repræsentation. Kræver mental visualisering eller kørsel af appen.
LæringsbarriereRelativt lav for simple layouts. Intuitivt for begyndere.Højere for begyndere. Kræver forståelse af NSLayoutConstraint og NSLayoutAnchor API'erne.
KompleksitetKan blive rodet og uoverskueligt for meget komplekse layouts med mange relationer. Merge-konflikter i teamarbejde er hyppige.Mere robust til komplekse, dynamiske eller genanvendelige layouts. Ingen merge-konflikter i kodefiler.
DebuggingVisuelle fejlindikatorer (røde/gule linjer) og indbygget debugger i Xcode.Kræver mere kodedebugging og forståelse af fejlmeddelelser fra Auto Layout-motoren.
GenanvendelighedSværere at genbruge specifikke layoutmønstre på tværs af flere storyboards/XIBs.Meget nem at genbruge. Du kan indkapsle layoutlogik i hjælperfunktioner eller brugerdefinerede visninger.
PerformanceMeget god. Xcode genererer optimerede constraints.Meget god. Kan være marginalt hurtigere under opstart, hvis mange visninger oprettes dynamisk.
VedligeholdelseNem at justere visuelt, men ændringer kan påvirke andre dele af layoutet uventet.Klar og præcis kontrol. Nemmere at forstå, hvad der sker, men kræver mere kode at skrive.

Mange udviklere vælger en hybrid tilgang, hvor de bruger Interface Builder til statiske, veldefinerede layouts og falder tilbage på programmatiske constraints for dynamiske komponenter eller for at opnå finere kontrol.

Ofte Stillede Spørgsmål om Auto Layout

Hvad er den mest almindelige fejl med Auto Layout?

Den mest almindelige fejl er at have enten manglende constraints eller modstridende constraints. Manglende constraints betyder, at Auto Layout ikke har nok information til at bestemme et elements position og størrelse entydigt (f.eks. en knap uden nogen positionelle constraints). Modstridende constraints opstår, når to eller flere constraints forsøger at diktere et element på en måde, der er umulig (f.eks. en bredde-constraint på 100 punkter og en anden på 200 punkter for det samme element). Xcode vil advare dig om disse problemer i Interface Builder, og runtime-fejl vil opstå i konsollen, hvis de ikke løses.

Kan Auto Layout erstatte alle former for manuel layout?

For langt de fleste standard brugerflader kan Auto Layout fuldstændigt erstatte manuel layout. Det er designet til at håndtere de fleste layoutscenarier effektivt. Der er dog niche-situationer, hvor manuel layout (ved at direkte indstille frame-egenskaben) stadig kan være nødvendig eller mere ligetil, især for meget komplekse animationer, avancerede brugerdefinerede visninger, der kræver pixel-perfekt kontrol, eller spil-lignende brugerflader, hvor ydeevne er absolut kritisk på et mikroniveau. For langt de fleste app-udviklere er Auto Layout dog den foretrukne og anbefalede metode.

Hvordan debugger jeg Auto Layout-problemer?

Xcode tilbyder flere værktøjer til debugging af Auto Layout:

  • Interface Builder Warnings: Se efter røde og gule ikoner i Interface Builder, som indikerer fejl eller advarsler.
  • Runtime Console Output: Auto Layout vil udskrive detaljerede fejlmeddelelser til konsollen, når der opstår tvetydige eller modstridende constraints under kørsel. Disse meddelelser kan være lange, men de indeholder ofte nøjagtige oplysninger om de problematiske constraints.
  • View Debugger: Xcodes View Debugger (et ikon, der ligner øjeæble i debug-området) giver en 3D-visning af din brugerflades hierarki og viser visuelt alle dine constraints, hvilket gør det nemt at identificere manglende eller overlappende elementer.
  • Programmatisk kontrol: Brug metoder som view.hasAmbiguousLayout eller view.constraintsAffectingLayout(for:) til programmatisk at tjekke for problemer under kørsel.

Er Auto Layout ydeevnekrævende?

Auto Layout er yderst optimeret af Apple og er generelt ikke en flaskehals for ydeevnen i de fleste iOS-apps. Auto Layout-motoren er designet til at være effektiv, selv med et stort antal constraints. De fleste ydeevneproblemer relateret til layout skyldes ofte ineffektiv brug af visningshierarkier (f.eks. for mange indlejrede visninger) eller at tvinge layoutopdateringer for ofte (f.eks. gentagne kald til layoutIfNeeded() i en loop uden grund), snarere end Auto Layout-systemet i sig selv. Korrekt brug af Auto Layout bidrager faktisk til en bedre ydeevne ved at reducere behovet for manuelt at beregne rammer og dermed minimere CPU-belastningen.

Konklusion

Auto Layout og constraints danner rygraden i responsivt iOS-design. Ved at forstå de grundlæggende principper for constraints og omfavne kraften i trait-variationer kan du bygge brugerflader, der elegant tilpasser sig det stadigt udviklende iOS-enhedslandskab. Uanset om du er nybegynder eller en erfaren udvikler, vil mestring af Auto Layout utvivlsomt forbedre din evne til at skabe visuelt tiltalende og brugervenlige apps på tværs af hele spektret af iOS-enheder. Begynd at implementere disse koncepter i dit næste projekt, og se dine layouts komme til live med fleksibilitet og elegance. God kodning!

Hvis du vil læse andre artikler, der ligner Mestring af Auto Layout & Constraints i iOS, kan du besøge kategorien Teknologi.

Go up