Hádanka: Zarovnání obsahu v UWP XAML

WinUI XAML

5 years ago

Zarovnávání obsahu v XAMLu se mi většinou zdá jendnodušší než v CSS. Tentorkát jsem se ale zasekl na zajímavém problému, který v závěru měl i elegantní řešení. Zkusme se na tu hádanku podívat společně!Uvažujme následující jednoduchý layout:

<Grid>
<Button HorizontalAlignment="Stretch" MaxWidth="250">Example</Button>
</Grid>

Máme roztažené tlačítko o maximální šířce 250 . Výsledek vypadá takto:

UWP button stretched centered

Co kdybychom nyní navíc chtěli, aby roztažené tlačítko bylo zarovnané doleva nebo doprava? Ukáže se, že to není úplně snadný problém. Nemůžeme použít zarovnání jako StartAndExpand a EndAndExpand - ty najdeme pouze v Xamarin.Forms. Nemůžeme ani nastavit HorizontalAlignment ve vnějším Gridu - Button by se tím zmenšil na nejmenší šířku, kterou skutečně potřebuje, takže by jeho roztažení již nemělo žádný vliv. Pokud si hádanku chcete vyřešit, přestaňte nyní číst a zkuste to sami! Pokud najdete jiné řešení než ukáži zde, rozhodně se o něj podělte v komentářích !

Zarovnání doleva

Atribut MaxWidth přesuneme do ColumnDefinition v naší mřížce a nastavíme tomuto sloupci šířku *:

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MaxWidth="250" />
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Stretch">Example</Button>
</Grid>

Tento sloupec mřížky je roztažený, ale má maximální šířku 250 . Sloupce v Gridu začínají na levém okraji, takže bude sloupec navíc doleva zarovnaný a tlačítko v něm roztažené na celou dostupnou šířku.

Left-aligned stretched button

Zarovnání doprava

Pro zarovnání doprava nám jeden sloupec nestačí, ale použijeme velmi analogický trik se dvěmi sloupci:

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" MaxWidth="250" />
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Stretch" Grid.Column="1">Example</Button>
</Grid>

Tlačítko nyní umístíme do druhého sloupce, který má stejné vlastnosti jako v předchozím příkladě. První sloupec má také šířku * a jeho smysl je zaplnění místa které zbyde po umístění sloupce druhého. Toto téměř funguje. Téměř - až na případ, kdy je okno úzké. V tu chvíli totiž dostane přednost pravidlo, že si sloupce se šířkou * v Gridu rovnoměrně rozdělí prostor který mají k dispozici - a oba sloupce tedy budou mít přesně poloviční šířku okna.

Narrow window evenly distributes Column widths

Musíme najít jinou cestu. Musíme Grid přesvědčit, že druhý sloupec má být výrazně širší než ten první:

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10000*" MaxWidth="250" />
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Stretch" Grid.Column="1">Example</Button>
</Grid>

Tím že jsme šířku druhého sloupce nastavili na 10000*, Grid bude automaticky předpokládat, že má být 10 000 krát širší než první sloupec. Díky MaxWidth tuto šířku ale zároveň omezíme na právě 250 a dostaneme přesně to, co jsme chtěli:

Right aligned stretched button

V případě, že jste našli jiné řešení této hádanky, určitě se o něj podělte v komentářích ??‍!