Riepilogo del capitolo 26. Layout personalizzati

Download Sample Scaricare l'esempio

Nota

Questo libro è stato pubblicato nella primavera del 2016, e non è stato aggiornato da allora. C'è molto nel libro che rimane prezioso, ma alcuni materiali sono obsoleti, e alcuni argomenti non sono più completamente corretti o completi.

Xamarin.Forms include diverse classi derivate da Layout<View>:

  • StackLayout,
  • Grid,
  • AbsoluteLayout e
  • RelativeLayout.

Questo capitolo descrive come creare classi personalizzate che derivano da Layout<View>.

Panoramica del layout

Non esiste un sistema centralizzato che gestisce Xamarin.Forms il layout. Ogni elemento è responsabile della determinazione delle proprie dimensioni e della modalità di rendering all'interno di una determinata area.

Genitori e figli

Ogni elemento con figli è responsabile del posizionamento di tali elementi all'interno di se stesso. È l'elemento padre che determina in definitiva le dimensioni dei relativi elementi figlio in base alle dimensioni disponibili e alle dimensioni desiderate per l'elemento figlio.

Ridimensionamento e posizionamento

Il layout inizia nella parte superiore della struttura ad albero visuale con la pagina e quindi procede in tutti i rami. Il metodo pubblico più importante nel layout è Layout definito da VisualElement. Ogni elemento padre di altri elementi chiama Layout ognuno dei relativi elementi figlio per assegnare all'elemento figlio una dimensione e una posizione rispetto a se stessa sotto forma di Rectangle valore. Queste Layout chiamate vengono propagate attraverso la struttura ad albero visuale.

È necessaria una chiamata a Layout per visualizzare un elemento sullo schermo e determina l'impostazione delle proprietà di sola lettura seguenti. Sono coerenti con l'oggetto Rectangle passato al metodo :

  • Bounds di tipo Rectangle
  • X di tipo double
  • Y di tipo double
  • Width di tipo double
  • Height di tipo double

Prima della Layout chiamata Height e Width avere valori fittizi pari a -1.

Una chiamata a Layout attiva anche le chiamate ai metodi protetti seguenti:

Infine, viene generato l'evento seguente:

Il OnSizeAllocated metodo viene sottoposto a override da Page e Layout, che sono le uniche due classi in che Xamarin.Forms possono avere elementi figlio. Chiamate al metodo sottoposto a override

LayoutChildrenLayout chiama quindi per ognuno degli elementi figlio dell'elemento. Se almeno un elemento figlio ha una nuova Bounds impostazione, viene generato l'evento seguente:

Vincoli e richieste di dimensioni

Per LayoutChildren chiamare Layout in modo intelligente su tutti i suoi figli, deve conoscere una dimensione preferita o desiderata per i bambini. Pertanto, le chiamate a Layout per ognuno degli elementi figlio sono generalmente precedute dalle chiamate a

Dopo la pubblicazione del libro, il GetSizeRequest metodo è stato deprecato e sostituito con

Il Measure metodo supporta la Margin proprietà e include un argomento di tipo MeasureFlag, che ha due membri:

Per molti elementi GetSizeRequest o Measure ottiene la dimensione nativa dell'elemento dal renderer. Entrambi i metodi hanno parametri per i vincoli di larghezza e altezza. Ad esempio, un Label userà il vincolo di larghezza per determinare come eseguire il wrapping di più righe di testo.

Sia GetSizeRequestche Measure restituiscono un valore di tipo SizeRequest, che ha due proprietà:

Molto spesso questi due valori sono gli stessi e il Minimum valore può essere in genere ignorato.

VisualElement definisce anche un metodo protetto simile a GetSizeRequest quello chiamato da GetSizeRequest:

Questo metodo è ora deprecato e sostituito con:

Ogni classe che deriva da Layout o Layout<T> deve eseguire l'override OnSizeRequest di o OnMeasure. Questa è la posizione in cui una classe di layout determina le proprie dimensioni, che in genere si basa sulle dimensioni dei relativi elementi figlio, che ottiene chiamando GetSizeRequest o Measure sugli elementi figlio. Prima e dopo la chiamata OnSizeRequest o OnMeasureo MeasureGetSizeRequest apporta modifiche in base alle proprietà seguenti:

  • WidthRequestdi tipo double, influisce sulla Request proprietà di SizeRequest
  • HeightRequest di tipo double, influisce sulla Request proprietà di SizeRequest
  • MinimumWidthRequest di tipo double, influisce sulla Minimum proprietà di SizeRequest
  • MinimumHeightRequest di tipo double, influisce sulla Minimum proprietà di SizeRequest

Vincoli infiniti

Gli argomenti del vincolo passati a GetSizeRequest (o Measure) e OnSizeRequest (o OnMeasure) possono essere infiniti (ad esempio, valori di Double.PositiveInfinity). Tuttavia, l'oggetto SizeRequest restituito da questi metodi non può contenere dimensioni infinite.

I vincoli infiniti indicano che le dimensioni richieste devono riflettere le dimensioni naturali dell'elemento. Una chiamata GetSizeRequest verticale StackLayout (o Measure) sui relativi elementi figlio con un vincolo di altezza infinita. Un layout dello stack orizzontale chiama GetSizeRequest (o Measure) sui relativi elementi figlio con un vincolo di larghezza infinito. GetSizeRequest Chiamate AbsoluteLayout (o Measure) sui relativi elementi figlio con vincoli di larghezza e altezza infiniti.

Peeking all'interno del processo

ExploreChildSize visualizza le informazioni sulle richieste di vincoli e dimensioni per un layout semplice.

Derivazione dalla visualizzazione layout<>

Una classe di layout personalizzata deriva da Layout<View>. Ha due responsabilità:

  • Eseguire l'override OnMeasure per chiamare Measure tutti gli elementi figlio del layout. Restituisce una dimensione richiesta per il layout stesso
  • Eseguire l'override LayoutChildren per chiamare Layout tutti gli elementi figlio del layout

Il for ciclo o foreach in queste sostituzioni deve ignorare qualsiasi elemento figlio la cui IsVisible proprietà è impostata su false.

Una chiamata a OnMeasure non è garantita. OnMeasure non verrà chiamato se l'elemento padre del layout controlla le dimensioni del layout, ad esempio un layout che riempie una pagina. Per questo motivo, LayoutChildren non può basarsi sulle dimensioni figlio ottenute durante la OnMeasure chiamata. Molto spesso, LayoutChildren deve chiamare Measure gli elementi figlio del layout oppure implementare una sorta di logica di memorizzazione nella cache delle dimensioni (da discutere in seguito).

Un semplice esempio

L'esempio VerticalStackDemo contiene una classe semplificata VerticalStack e una dimostrazione dell'uso.

Posizionamento verticale e orizzontale semplificato

Uno dei processi che VerticalStack devono essere eseguiti durante l'override LayoutChildren . Il metodo usa la proprietà dell'elemento HorizontalOptions figlio per determinare come posizionare l'elemento figlio all'interno dello VerticalStackslot in . È invece possibile chiamare il metodo Layout.LayoutChildIntoBoundingRectstatico . Questo metodo chiama Measure sull'elemento figlio e usa le relative HorizontalOptions proprietà e VerticalOptions per posizionare l'elemento figlio all'interno del rettangolo specificato.

Invalidazione

Spesso una modifica nella proprietà di un elemento influisce sulla modalità di visualizzazione dell'elemento nel layout. Il layout deve essere invalidato per attivare un nuovo layout.

VisualElement definisce un metodo InvalidateMeasureprotetto , che viene in genere chiamato dal gestore delle proprietà modificate di qualsiasi proprietà associabile la cui modifica influisce sulle dimensioni dell'elemento. Il InvalidateMeasure metodo genera un MeasureInvalidated evento.

La Layout classe definisce un metodo protetto simile denominato InvalidateLayout, che un Layout derivato deve chiamare per qualsiasi modifica che influisca sulla posizione e sulle dimensioni dei relativi elementi figlio.

Alcune regole per il codice dei layout

  1. Le proprietà definite dai Layout<T> derivati devono essere supportate da proprietà associabili e i gestori delle proprietà modificate devono chiamare InvalidateLayout.

  2. Un Layout<T> derivato che definisce le proprietà associabili associate deve eseguire l'override OnAdded per aggiungere un gestore modificato dalla proprietà ai relativi elementi figlio e OnRemoved rimuovere tale gestore. Il gestore deve verificare la presenza di modifiche in queste proprietà associabili associate e rispondere chiamando InvalidateLayout.

  3. Una Layout<T> derivata che implementa una cache di dimensioni figlio deve eseguire l'override e OnChildMeasureInvalidated cancellare InvalidateLayout la cache quando questi metodi vengono chiamati.

Layout con proprietà

La WrapLayout classe in Xamarin.FormsBook.Toolkit presuppone che tutti i relativi elementi figlio siano le stesse dimensioni e eseponga gli elementi figlio da una riga (o colonna) alla successiva. Definisce una Orientation proprietà come StackLayout, e ColumnSpacing e RowSpacing proprietà come Gride e memorizza nella cache le dimensioni figlio.

L'esempio PhotoWrap inserisce in un oggetto WrapLayoutScrollView per la visualizzazione di foto di magazzino.

Non sono consentite dimensioni non vincolate!

L'oggetto UniformGridLayout nella Xamarin.Formslibreria Book.Toolkit è destinato a visualizzare tutti i relativi elementi figlio all'interno di se stesso. Pertanto, non può gestire dimensioni non vincolate e genera un'eccezione se ne viene rilevata una.

L'esempio PhotoGrid illustra UniformGridLayout:

Triple screenshot of Photo Grid

Elementi figlio sovrapposti

Un Layout<T> derivato può sovrapporsi ai relativi elementi figlio. Tuttavia, il rendering degli elementi figlio viene eseguito nell'ordine Children nella raccolta e non nell'ordine in cui vengono chiamati i relativi Layout metodi.

La Layout classe definisce due metodi che consentono di spostare un elemento figlio all'interno della raccolta:

  • LowerChild per spostare un elemento figlio all'inizio della raccolta
  • RaiseChild per spostare un elemento figlio alla fine della raccolta

Per gli elementi figlio sovrapposti, gli elementi figlio alla fine della raccolta vengono visualizzati visivamente sopra gli elementi figlio all'inizio della raccolta.

La OverlapLayout classe nella Xamarin.Formslibreria Book.Toolkit definisce una proprietà associata per indicare l'ordine di rendering e quindi consentire la visualizzazione di uno dei relativi elementi figlio sopra gli altri. L'esempio StudentCardFile illustra quanto segue:

Triple screenshot of Student Card File Grid

Altre proprietà associabili associate

La CartesianLayout classe nella Xamarin.Formslibreria Book.Toolkit definisce le proprietà associabili associate per specificare due Point valori e un valore di spessore e modifica gli BoxView elementi per assomigliare alle linee.

Nell'esempio UnitCube viene usato per disegnare un cubo 3D.

Layout e layoutTo

Un Layout<T> derivato può chiamare LayoutTo anziché Layout animare il layout. La AnimatedCartesianLayout classe esegue questa operazione e l'esempio AnimatedUnitCube lo dimostra.