Xamarin.Forms Visual State Manager
Pomocí Správce stavu vizuálu můžete provádět změny elementů XAML na základě vizuálních stavů nastavených z kódu.
Visual State Manager (VSM) poskytuje strukturovaný způsob, jak provádět vizuální změny uživatelského rozhraní z kódu. Ve většině případů je uživatelské rozhraní aplikace definováno v jazyce XAML a tento XAML obsahuje značky popisující, jak Správce stavu vizuálu ovlivňuje vizuály uživatelského rozhraní.
Virtuální počítač představuje koncept vizuálních stavů. Zobrazení Xamarin.Forms , jako Button
je například, může mít několik různých vzhledů vizuálů v závislosti na jeho základním stavu – bez ohledu na to, jestli je zakázané, nebo stisknuté nebo má fokus vstupu. Toto jsou stavy tlačítka.
Stavy vizuálů se shromažďují ve skupinách stavů vizuálů. Všechny stavy vizuálů ve skupině stavů vizuálu se vzájemně vylučují. Vizuální stavy i skupiny stavů vizuálů jsou identifikovány jednoduchými textovými řetězci.
Správce Xamarin.Forms stavu vizuálu definuje jednu skupinu stavů vizuálu s názvem CommonStates s následujícími stavy vizuálu:
- "Normální"
- "Zakázáno"
- "Prioritní"
- "Vybráno"
Tato skupina stavů vizuálu je podporována pro všechny třídy odvozené od VisualElement
, což je základní třída pro View
a Page
.
Můžete také definovat vlastní skupiny stavů vizuálů a stavy vizuálů, jak ukazuje tento článek.
Poznámka:
Xamarin.Forms vývojáři obeznámení s triggery vědí, že triggery mohou také provádět změny vizuálů v uživatelském rozhraní na základě změn ve vlastnostech zobrazení nebo spouštění událostí. Použití triggerů k řešení různých kombinací těchto změn ale může být docela matoucí. V historických prostředích založených na jazyce Windows XAML byl představen Správce vizuálního stavu, aby se zmírnit nejasnost vyplývající z kombinací vizuálních stavů. U virtuálního počítače se vizuály ve skupině stavů vizuálu vždy vzájemně vylučují. Aktuální stav je vždy jen jeden stav v každé skupině.
Běžné stavy
Správce vizuálního stavu umožňuje zahrnout do souboru XAML revize, které můžou změnit vzhled zobrazení, pokud je zobrazení normální nebo zakázané nebo má vstupní fokus. Ty se označují jako běžné státy.
Předpokládejme například, že máte Entry
na stránce zobrazení a chcete, aby se vzhled vizuálu Entry
změnil následujícími způsoby:
- Pokud
Entry
je tato možnost zakázanáEntry
, měla by mít růžové pozadí. - Normálně
Entry
by měl mít limetkové pozadí. - Pokud
Entry
má vstupní fokus, měl by se rozbalit na dvojnásobek jeho normální výšky.
Kód VSM můžete připojit k jednotlivým zobrazením nebo ho můžete definovat ve stylu, pokud se vztahuje na více zobrazení. Následující dvě části popisují tyto přístupy.
Revize VSM v zobrazení
Pokud chcete k zobrazení připojit značky Entry
VSM, nejprve oddělte Entry
počáteční a koncové značky:
<Entry FontSize="18">
</Entry>
Má explicitní velikost písma, protože jeden ze stavů použije FontSize
vlastnost zdvojnásobit velikost textu v objektu Entry
.
Potom mezi tyto značky vložte VisualStateManager.VisualStateGroups
značky:
<Entry FontSize="18">
<VisualStateManager.VisualStateGroups>
</VisualStateManager.VisualStateGroups>
</Entry>
VisualStateGroups
je připojená bindable vlastnost definovaná VisualStateManager
třídou. (Další informace o připojených vlastnostech bindable naleznete v článku Připojené vlastnosti.) Takto je VisualStateGroups
vlastnost připojena k objektu Entry
.
Vlastnost VisualStateGroups
je typu VisualStateGroupList
, což je kolekce VisualStateGroup
objektů. VisualStateManager.VisualStateGroups
Do značek vložte pár VisualStateGroup
značek pro každou skupinu stavů vizuálů, které chcete zahrnout:
<Entry FontSize="18">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Entry>
Všimněte si, že VisualStateGroup
značka má x:Name
atribut označující název skupiny. Třída VisualStateGroup
definuje Name
vlastnost, kterou můžete použít místo toho:
<VisualStateGroup Name="CommonStates">
Můžete použít buď x:Name
nebo Name
ne oba ve stejném prvku.
Třída VisualStateGroup
definuje vlastnost s názvem States
, což je kolekce VisualState
objektů. States
je vlastnost VisualStateGroups
obsahu, takže můžete zahrnout VisualState
značky přímo mezi značkyVisualStateGroup
. (Vlastnosti obsahu jsou popsány v článku. Základní syntaxe XAML.)
Dalším krokem je zahrnutí dvojice značek pro každý stav vizuálu v této skupině. Můžete je také identifikovat pomocí:x:Name
Name
<Entry FontSize="18">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
</VisualState>
<VisualState x:Name="Focused">
</VisualState>
<VisualState x:Name="Disabled">
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Entry>
VisualState
definuje vlastnost s názvem Setters
, což je kolekce Setter
objektů. Jedná se o stejné Setter
objekty, které používáte v objektu Style
.
Setters
není vlastnost VisualState
obsahu , takže je nutné zahrnout značky elementu vlastnosti pro Setters
vlastnost:
<Entry FontSize="18">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Focused">
<VisualState.Setters>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Entry>
Mezi každou dvojici Setters
značek teď můžete vložit jeden nebo více Setter
objektů. Toto jsou Setter
objekty, které definují stavy vizuálů popsané výše:
<Entry FontSize="18">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Property="FontSize" Value="36" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Pink" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Entry>
Každá Setter
značka označuje hodnotu konkrétní vlastnosti, pokud je tento stav aktuální. Všechny vlastnosti odkazované objektem Setter
musí být zajištěny vazebnou vlastností.
Revize podobná tomu je základem virtuálního počítače na stránce Zobrazení v ukázkovém programu. Stránka obsahuje tři Entry
zobrazení, ale k ní je připojena pouze druhá značka virtuálního počítače:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:VsmDemos"
x:Class="VsmDemos.MainPage"
Title="VSM Demos">
<StackLayout>
<StackLayout.Resources>
<Style TargetType="Entry">
<Setter Property="Margin" Value="20, 0" />
<Setter Property="FontSize" Value="18" />
</Style>
<Style TargetType="Label">
<Setter Property="Margin" Value="20, 30, 20, 0" />
<Setter Property="FontSize" Value="Large" />
</Style>
</StackLayout.Resources>
<Label Text="Normal Entry:" />
<Entry />
<Label Text="Entry with VSM: " />
<Entry>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Property="FontSize" Value="36" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Pink" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Entry.Triggers>
<DataTrigger TargetType="Entry"
Binding="{Binding Source={x:Reference entry3},
Path=Text.Length}"
Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Entry.Triggers>
</Entry>
<Label Text="Entry to enable 2nd Entry:" />
<Entry x:Name="entry3"
Text=""
Placeholder="Type something to enable 2nd Entry" />
</StackLayout>
</ContentPage>
Všimněte si, že druhá Entry
má DataTrigger
také v rámci své Trigger
kolekce. To způsobí Entry
, že bude zakázána, dokud se něco netypuje do třetí Entry
. Tady je stránka při spuštění v iOSu, Androidu a Univerzální platforma Windows (UPW):
Aktuální stav vizuálu je "Zakázáno", takže pozadí druhé Entry
je růžové na obrazovkách s iOSem a Androidem. Implementace Entry
UPW nepovoluje nastavení barvy pozadí při zakázání Entry
.
Když zadáte nějaký text do třetího Entry
, druhý Entry
se přepne do stavu "Normální" a pozadí je nyní vápeno:
Když se dotknete druhého Entry
, dostane vstupní fokus. Přepne do stavu Prioritní a rozšíří se o dvojnásobek jeho výšky:
Všimněte si, že Entry
při získání vstupního fokusu nezachová pozadí limetkového pozadí. Když Správce stavu vizuálu přepíná mezi stavy vizuálu, vlastnosti nastavené předchozím stavem nejsou nastaveny. Mějte na paměti, že se vizuální stavy vzájemně vylučují. Stav "Normální" neznamená pouze to, že Entry
je povolen. Znamená to, že Entry
je povolená a nemá fokus vstupu.
Pokud chcete Entry
, aby měl vápno ve stavu Prioritní, přidejte do tohoto vizuálního stavu další Setter
:
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Property="FontSize" Value="36" />
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
Aby tyto Setter
objekty fungovaly správně, VisualStateGroup
musí obsahovat VisualState
objekty pro všechny stavy v této skupině. Pokud existuje vizuální stav, který neobsahuje žádné Setter
objekty, zahrňte ho přesto jako prázdnou značku:
<VisualState x:Name="Normal" />
Revize Visual State Manageru ve stylu
Často je nutné sdílet stejné revize visual state manageru mezi dvěma nebo více zobrazeními. V tomto případě budete chtít kód vložit do Style
definice.
Tady je existující implicitní Style
pro Entry
prvky na stránce zobrazení virtuálního počítače:
<Style TargetType="Entry">
<Setter Property="Margin" Value="20, 0" />
<Setter Property="FontSize" Value="18" />
</Style>
Přidejte Setter
značky pro připojenou VisualStateManager.VisualStateGroups
vlastnost bindable:
<Style TargetType="Entry">
<Setter Property="Margin" Value="20, 0" />
<Setter Property="FontSize" Value="18" />
<Setter Property="VisualStateManager.VisualStateGroups">
</Setter>
</Style>
Vlastnost obsahu je Setter
Value
, takže hodnotu Value
vlastnosti lze zadat přímo v rámci těchto značek. Tato vlastnost je typu VisualStateGroupList
:
<Style TargetType="Entry">
<Setter Property="Margin" Value="20, 0" />
<Setter Property="FontSize" Value="18" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
</VisualStateGroupList>
</Setter>
</Style>
V těchto značkách můžete zahrnout jeden z více VisualStateGroup
objektů:
<Style TargetType="Entry">
<Setter Property="Margin" Value="20, 0" />
<Setter Property="FontSize" Value="18" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
Zbývající kód VSM je stejný jako předtím.
Tady je stránka VSM ve stylu zobrazující kompletní revize virtuálního počítače:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="VsmDemos.VsmInStylePage"
Title="VSM in Style">
<StackLayout>
<StackLayout.Resources>
<Style TargetType="Entry">
<Setter Property="Margin" Value="20, 0" />
<Setter Property="FontSize" Value="18" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Property="FontSize" Value="36" />
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Pink" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Label">
<Setter Property="Margin" Value="20, 30, 20, 0" />
<Setter Property="FontSize" Value="Large" />
</Style>
</StackLayout.Resources>
<Label Text="Normal Entry:" />
<Entry />
<Label Text="Entry with VSM: " />
<Entry>
<Entry.Triggers>
<DataTrigger TargetType="Entry"
Binding="{Binding Source={x:Reference entry3},
Path=Text.Length}"
Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Entry.Triggers>
</Entry>
<Label Text="Entry to enable 2nd Entry:" />
<Entry x:Name="entry3"
Text=""
Placeholder="Type something to enable 2nd Entry" />
</StackLayout>
</ContentPage>
Teď všechna Entry
zobrazení na této stránce reagují stejným způsobem na jejich vizuální stavy. Všimněte si také, že stav "Prioritní" teď obsahuje sekundu Setter
, která každému pozadí vápna dává Entry
také, když má vstupní fokus:
Stavy vizuálů v Xamarin.Forms
Následující tabulka uvádí stavy vizuálů, které jsou definovány v Xamarin.Forms:
Třída | Stavy | Další informace |
---|---|---|
Button |
Pressed |
Stavy vizuálů tlačítek |
CheckBox |
IsChecked |
Stavy vizuálu CheckBox |
CarouselView |
DefaultItem , CurrentItem , , PreviousItem NextItem |
Stavy vizuálu CarouselView |
ImageButton |
Pressed |
Stavy vizuálu ImageButton |
RadioButton |
Checked , Unchecked |
Stavy vizuálu RadioButton |
Switch |
On , Off |
Přepnutí stavů vizuálů |
VisualElement |
Normal , Disabled , , Focused Selected |
Běžné stavy |
Každý z těchto stavů je přístupný prostřednictvím skupiny stavů vizuálu s názvem CommonStates
.
Kromě toho CollectionView
implementuje Selected
stav. Další informace naleznete v tématu Změna barvy vybrané položky.
Nastavení stavu u více prvků
Vpředchozíchch Je však také možné vytvořit vizuální stavy, které jsou připojeny k jednomu prvku, ale které nastaví vlastnosti na jiných prvcích ve stejném oboru. Vyhnete se tak opakování vizuálních stavů u každého prvku, na kterém stavy pracují.
Typ Setter
má TargetName
vlastnost typu string
, která představuje cílový prvek, který Setter
bude stav vizuálu manipulovat. TargetName
Pokud je vlastnost definována, Setter
nastaví Property
element definovaný v TargetName
:Value
<Setter TargetName="label"
Property="Label.TextColor"
Value="Red" />
V tomto příkladu bude mít pojmenovaná Label
label
vlastnost nastavena na Red
.TextColor
Při nastavování TargetName
vlastnosti je nutné zadat úplnou cestu k vlastnosti v .Property
Proto je vlastnost nastavena TextColor
na Label
, Property
je zadána jako Label.TextColor
.
Poznámka:
Všechny vlastnosti odkazované objektem Setter
musí být zajištěny vazebnou vlastností.
Virtuální počítač se stránkou Setter TargetName v ukázce ukazuje, jak nastavit stav u více prvků z jedné skupiny stavů vizuálu. Soubor XAML se skládá z elementu StackLayout
, elementu Label
Entry
a a Button
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="VsmDemos.VsmSetterTargetNamePage"
Title="VSM with Setter TargetName">
<StackLayout Margin="10">
<Label Text="What is the capital of France?" />
<Entry x:Name="entry"
Placeholder="Enter answer" />
<Button Text="Reveal answer">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Property="Scale"
Value="0.8" />
<Setter TargetName="entry"
Property="Entry.Text"
Value="Paris" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Button>
</StackLayout>
</ContentPage>
Kód VSM je připojen k objektu StackLayout
. Existují dva vzájemně se vylučující stavy s názvem "Normální" a "Stisknuto", přičemž každý stav obsahuje VisualState
značky.
Stav "Normální" je aktivní, když Button
není stisknuto, a odpověď na otázku může být zadána:
Po stisknutí se stav "Stisknuto" změní na Button
aktivní:
"Pressed" VisualState
určuje, že když Button
je stisknuto, jeho Scale
vlastnost bude změněna z výchozí hodnoty 1 na 0,8. Kromě toho bude Text
mít pojmenovaná Entry
entry
vlastnost nastavena na Paříž. Výsledkem je proto, že když Button
je stisknuto, bude o něco menší a Entry
zobrazí Paříž. Po Button
vydání se pak škáluje na výchozí hodnotu 1 a Entry
zobrazí všechny dříve zadané texty.
Důležité
Cesty k vlastnostem nejsou v současné době podporovány v Setter
elementech, které určují TargetName
vlastnost.
Definování vlastních stavů vizuálů
Každá třída odvozená od VisualElement
podpory běžných stavů "Normální", "Prioritní" a "Zakázáno". Kromě toho CollectionView
třída podporuje "Selected" stav. Třída interně rozpozná, VisualElement
kdy se aktivuje nebo zakáže, nebo jestli je fokusovaná, a volá statickou VisualStateManager.GoToState
metodu:
VisualStateManager.GoToState(this, "Focused");
Toto je jediný kód visual state manageru, který najdete ve VisualElement
třídě. Vzhledem k tomu GoToState
, že je volána pro každý objekt založený na každé třídě, která je odvozena , VisualElement
můžete použít Visual State Manager s libovolným VisualElement
objektem reagovat na tyto změny.
Zajímavé je, že název skupiny stavů vizuálu "CommonStates" není explicitně odkazován v VisualElement
. Název skupiny není součástí rozhraní API pro Visual State Manager. V rámci jednoho z dosud zobrazených dvou ukázkových programů můžete změnit název skupiny z commonstates na cokoli jiného a program bude dál fungovat. Název skupiny je pouze obecný popis stavů v této skupině. Implicitně se rozumí tomu, že vizuální stavy v jakékoli skupině se vzájemně vylučují: Jeden stav a vždy je aktuální jenom jeden stav.
Pokud chcete implementovat vlastní vizuální stavy, budete muset volat VisualStateManager.GoToState
z kódu. Nejčastěji toto volání provedete ze souboru kódu třídy stránky.
Stránka Ověření virtuálního počítače v ukázce ukazuje, jak používat Visual State Manager v souvislosti s ověřováním vstupu. Soubor XAML se skládá ze StackLayout
dvou Label
prvků:Entry
Button
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="VsmDemos.VsmValidationPage"
Title="VSM Validation">
<StackLayout x:Name="stackLayout"
Padding="10, 10">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="ValidityStates">
<VisualState Name="Valid">
<VisualState.Setters>
<Setter TargetName="helpLabel"
Property="Label.TextColor"
Value="Transparent" />
<Setter TargetName="entry"
Property="Entry.BackgroundColor"
Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Invalid">
<VisualState.Setters>
<Setter TargetName="entry"
Property="Entry.BackgroundColor"
Value="Pink" />
<Setter TargetName="submitButton"
Property="Button.IsEnabled"
Value="False" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Label Text="Enter a U.S. phone number:"
FontSize="Large" />
<Entry x:Name="entry"
Placeholder="555-555-5555"
FontSize="Large"
Margin="30, 0, 0, 0"
TextChanged="OnTextChanged" />
<Label x:Name="helpLabel"
Text="Phone number must be of the form 555-555-5555, and not begin with a 0 or 1" />
<Button x:Name="submitButton"
Text="Submit"
FontSize="Large"
Margin="0, 20"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
Kód VSM je připojený k (pojmenované StackLayout
stackLayout
). Existují dva vzájemně se vylučující stavy s názvem "Valid" a "Invalid", přičemž každý stav obsahuje VisualState
značky.
Entry
Pokud neobsahuje platné telefonní číslo, aktuální stav je neplatný, takže Entry
má růžové pozadí, druhá Label
je viditelná a Button
je zakázaná:
Po zadání platného telefonního čísla se aktuální stav změní na "Platné". Získá Entry
vápno pozadí, druhý Label
zmizí a Button
je nyní povolen:
Soubor kódu je zodpovědný za zpracování TextChanged
události z objektu Entry
. Obslužná rutina používá regulární výraz k určení, jestli je vstupní řetězec platný nebo ne. Metoda v souboru kódu s názvem volá GoToState
statickou VisualStateManager.GoToState
metodu pro stackLayout
:
public partial class VsmValidationPage : ContentPage
{
public VsmValidationPage()
{
InitializeComponent();
GoToState(false);
}
void OnTextChanged(object sender, TextChangedEventArgs args)
{
bool isValid = Regex.IsMatch(args.NewTextValue, @"^[2-9]\d{2}-\d{3}-\d{4}$");
GoToState(isValid);
}
void GoToState(bool isValid)
{
string visualState = isValid ? "Valid" : "Invalid";
VisualStateManager.GoToState(stackLayout, visualState);
}
}
Všimněte si také, že GoToState
metoda je volána z konstruktoru k inicializaci stavu. Vždy by měl existovat aktuální stav. Ale nikde v kódu není žádný odkaz na název skupiny stavů vizuálu, i když je odkazován v XAML jako "ValidationStates" pro účely srozumitelnosti.
Všimněte si, že soubor kódu za kódem musí vzít v úvahu pouze objekt na stránce, který definuje stavy vizuálu, a volat VisualStateManager.GoToState
pro tento objekt. Důvodem je to, že oba vizuály cílí na více objektů na stránce.
Možná vás zajímá: Pokud soubor kódu za kódem musí odkazovat na objekt na stránce, která definuje vizuální stavy, proč nemůže soubor kódu jednoduše přistupovat k tomuto a dalším objektům přímo? Určitě by to mohlo. Výhodou použití virtuálního počítače je ale to, že můžete řídit, jak vizuální prvky reagují na jiný stav zcela v XAML, což udržuje veškerý návrh uživatelského rozhraní na jednom místě. Tím se zabrání nastavení vzhledu vizuálu tak, že přistupujete k vizuálním prvkům přímo z kódu.
Triggery vizuálního stavu
Vizuální stavy podporují triggery stavu, což je specializovaná skupina triggerů, které definují podmínky, za kterých VisualState
se mají použít.
Aktivační události stavu se přidají do StateTriggers
kolekce objektu VisualState
. Tato kolekce může obsahovat jednu aktivační událost stavu nebo více aktivačních událostí stavu. A VisualState
se použije, když jsou aktivní všechny aktivační události stavu v kolekci.
Při použití aktivačních událostí stavu k řízení stavů Xamarin.Forms vizuálů používá následující pravidla priority k určení, která aktivační událost (a odpovídající VisualState
) bude aktivní:
- Jakákoli aktivační událost, která je odvozena od
StateTriggerBase
. - Aktivované
AdaptiveTrigger
z důvoduMinWindowWidth
splnění podmínky. - Aktivované
AdaptiveTrigger
z důvoduMinWindowHeight
splnění podmínky.
Pokud je více aktivačních událostí současně aktivních (například dva vlastní triggery), má přednost první aktivační událost deklarovaná v kódu.
Další informace o aktivačních událostech stavu najdete v tématu Aktivační události stavu.
Použití Visual State Manageru pro adaptivní rozložení
Xamarin.Forms Aplikace spuštěná na telefonu se obvykle dá zobrazit v poměru stran na výšku nebo na šířku a Xamarin.Forms program spuštěný na ploše se dá změnit tak, aby předpokládal mnoho různých velikostí a poměrů stran. Dobře navržená aplikace může u těchto různých faktorů formuláře stránky nebo okna zobrazit svůj obsah odlišně.
Tato technika se někdy označuje jako adaptivní rozložení. Vzhledem k tomu, že adaptivní rozložení zahrnuje pouze vizuály programu, je to ideální aplikace správce vizuálního stavu.
Jednoduchým příkladem je aplikace, která zobrazuje malou kolekci tlačítek, které ovlivňují obsah aplikace. V režimu na výšku se tato tlačítka můžou zobrazovat ve vodorovném řádku v horní části stránky:
V režimu na šířku se pole tlačítek může přesunout na jednu stranu a zobrazit ve sloupci:
Shora dolů program běží na Univerzální platforma Windows, Androidu a iOSu.
Stránka adaptivního rozložení virtuálního počítače v ukázce definuje skupinu s názvem "OrientationStates" se dvěma stavy vizuálů s názvem Na výšku a Na šířku. (Složitější přístup může být založený na několika různých šířkách stránek nebo oken.)
Kód VSM se vyskytuje na čtyřech místech v souboru XAML. Pojmenovaný StackLayout
mainStack
obsahuje nabídku i obsah, což je Image
prvek. To StackLayout
by mělo mít svislou orientaci v režimu na výšku a vodorovnou orientaci v režimu na šířku:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="VsmDemos.VsmAdaptiveLayoutPage"
Title="VSM Adaptive Layout">
<StackLayout x:Name="mainStack">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="OrientationStates">
<VisualState Name="Portrait">
<VisualState.Setters>
<Setter Property="Orientation" Value="Vertical" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Landscape">
<VisualState.Setters>
<Setter Property="Orientation" Value="Horizontal" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ScrollView x:Name="menuScroll">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="OrientationStates">
<VisualState Name="Portrait">
<VisualState.Setters>
<Setter Property="Orientation" Value="Horizontal" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Landscape">
<VisualState.Setters>
<Setter Property="Orientation" Value="Vertical" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackLayout x:Name="menuStack">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="OrientationStates">
<VisualState Name="Portrait">
<VisualState.Setters>
<Setter Property="Orientation" Value="Horizontal" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Landscape">
<VisualState.Setters>
<Setter Property="Orientation" Value="Vertical" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackLayout.Resources>
<Style TargetType="Button">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup Name="OrientationStates">
<VisualState Name="Portrait">
<VisualState.Setters>
<Setter Property="HorizontalOptions" Value="CenterAndExpand" />
<Setter Property="Margin" Value="10, 5" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Landscape">
<VisualState.Setters>
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="Margin" Value="10" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</StackLayout.Resources>
<Button Text="Banana"
Command="{Binding SelectedCommand}"
CommandParameter="Banana.jpg" />
<Button Text="Face Palm"
Command="{Binding SelectedCommand}"
CommandParameter="FacePalm.jpg" />
<Button Text="Monkey"
Command="{Binding SelectedCommand}"
CommandParameter="monkey.png" />
<Button Text="Seated Monkey"
Command="{Binding SelectedCommand}"
CommandParameter="SeatedMonkey.jpg" />
</StackLayout>
</ScrollView>
<Image x:Name="image"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>
Vnitřní ScrollView
název menuScroll
a pojmenovaná StackLayout
menuStack
implementace nabídky tlačítek. Orientace těchto rozložení je opakem mainStack
. Nabídka by měla být vodorovná v režimu na výšku a svislá v režimu na šířku.
Čtvrtý oddíl kódu VSM je implicitní styl tlačítek samotných. Tento kód nastaví VerticalOptions
a HorizontalOptions
Margin
vlastnosti specifické pro orientaci na výšku a na šířku.
Soubor kódu nastaví BindingContext
vlastnost menuStack
pro implementaci Button
příkazů a také připojí obslužnou rutinu SizeChanged
k události stránky:
public partial class VsmAdaptiveLayoutPage : ContentPage
{
public VsmAdaptiveLayoutPage ()
{
InitializeComponent ();
SizeChanged += (sender, args) =>
{
string visualState = Width > Height ? "Landscape" : "Portrait";
VisualStateManager.GoToState(mainStack, visualState);
VisualStateManager.GoToState(menuScroll, visualState);
VisualStateManager.GoToState(menuStack, visualState);
foreach (View child in menuStack.Children)
{
VisualStateManager.GoToState(child, visualState);
}
};
SelectedCommand = new Command<string>((filename) =>
{
image.Source = ImageSource.FromResource("VsmDemos.Images." + filename);
});
menuStack.BindingContext = this;
}
public ICommand SelectedCommand { private set; get; }
}
Obslužná rutina SizeChanged
volá tyto dva StackLayout
prvky a ScrollView
potom prochází podřízené menuStack
prvky volání VisualStateManager.GoToState
prvků Button
VisualStateManager.GoToState
.
Může se zdát, že soubor s kódem za kódem může zpracovávat změny orientace přímo nastavením vlastností prvků v souboru XAML, ale Správce vizuálního stavu je rozhodně strukturovanější přístup. Všechny vizuály se uchovávají v souboru XAML, kde se snadněji prověřují, udržují a upravují.
Visual State Manager s Xamarin.University
Xamarin.Forms 3.0 Video o Visual State Manageru