Riepilogo del capitolo 26. Layout personalizzati
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
eRelativeLayout
.
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 tipoRectangle
X
di tipodouble
Y
di tipodouble
Width
di tipodouble
Height
di tipodouble
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:
SizeAllocated
, che chiamaOnSizeAllocated
, che può essere sottoposto a override.
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
UpdateChildrenLayout
perPage
derivati eUpdateChildrenLayout
perLayout
derivati, che chiamaLayoutChildren
perPage
derivati eLayoutChildren
perLayout
derivati.
LayoutChildren
Layout
chiama quindi per ognuno degli elementi figlio dell'elemento. Se almeno un elemento figlio ha una nuova Bounds
impostazione, viene generato l'evento seguente:
LayoutChanged
perPage
derivati eLayoutChanged
perLayout
derivati
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:
IncludeMargins
None
per non includere margini
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 GetSizeRequest
che 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
:
OnSizeRequest
restituisce unSizeRequest
valore
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 OnMeasure
o Measure
GetSizeRequest
apporta modifiche in base alle proprietà seguenti:
WidthRequest
di tipodouble
, influisce sullaRequest
proprietà diSizeRequest
HeightRequest
di tipodouble
, influisce sullaRequest
proprietà diSizeRequest
MinimumWidthRequest
di tipodouble
, influisce sullaMinimum
proprietà diSizeRequest
MinimumHeightRequest
di tipodouble
, influisce sullaMinimum
proprietà diSizeRequest
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 chiamareMeasure
tutti gli elementi figlio del layout. Restituisce una dimensione richiesta per il layout stesso - Eseguire l'override
LayoutChildren
per chiamareLayout
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 VerticalStack
slot in . È invece possibile chiamare il metodo Layout.LayoutChildIntoBoundingRect
statico . 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 InvalidateMeasure
protetto , 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
Le proprietà definite dai
Layout<T>
derivati devono essere supportate da proprietà associabili e i gestori delle proprietà modificate devono chiamareInvalidateLayout
.Un
Layout<T>
derivato che definisce le proprietà associabili associate deve eseguire l'overrideOnAdded
per aggiungere un gestore modificato dalla proprietà ai relativi elementi figlio eOnRemoved
rimuovere tale gestore. Il gestore deve verificare la presenza di modifiche in queste proprietà associabili associate e rispondere chiamandoInvalidateLayout
.Una
Layout<T>
derivata che implementa una cache di dimensioni figlio deve eseguire l'override eOnChildMeasureInvalidated
cancellareInvalidateLayout
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 Grid
e e memorizza nella cache le dimensioni figlio.
L'esempio PhotoWrap inserisce in un oggetto WrapLayout
ScrollView
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
:
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 raccoltaRaiseChild
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:
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.