Как сделать макет с учетом размера экрана?
Я делаю настольную игру. Чтобы построить доску, я делаю следующее:
// adapted from http://code.msdn.microsoft.com/windowsapps/Reversi-XAMLC-sample-board-816140fa/sourcecode?fileId=69011&pathId=706708707
// This is shit code.
async void PlayGame_Loaded(object sender, RoutedEventArgs e)
{
foreach (var row in Game.ALL_ROWS)
{
boardGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(BOARD_GRID_SIDE_LENGTH) });
}
var maxColIndex = Game.ALL_ROWS.Max();
foreach (var col in Enumerable.Range(0, maxColIndex))
{
boardGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(BOARD_GRID_SIDE_LENGTH) });
}
// ...
}
(Не стесняйтесь предлагать альтернативные подходы.)
По сути, я создаю кучу строк и столбцов на основе заданной высоты и ширины и заполняю эти строки и столбцы пробелами. Это прекрасно работает, когда я устанавливаю длину строк и столбцов для своего ноутбука, но, очевидно, это не будет работать на устройствах с другим разрешением. (Например, он урезан на Surface RT.) Как мне обойти это? Могу ли я указать длину стороны, которая является частью родительского контейнера? Какова лучшая практика здесь?
3 ответа
Я использую это:
var bounds = Window.Current.Bounds;
double height = bounds.Height;
double width = bounds.Width;
чтобы узнать разрешение экрана, на котором находятся мои приложения, а затем изменить размеры элементов сетки в зависимости от размера экрана.
РЕДАКТИРОВАТЬ: Так что для вашего кода я бы сделал:
async void PlayGame_Loaded(object sender, RoutedEventArgs e)
{
var bounds = Window.Current.Bounds;
double BOARD_GRID_SIDE_LENGTH = bounds.Height;
double BOARD_GRID_SIDE_WIDTH = bounds.Width;
foreach (var row in Game.ALL_ROWS)
{
boardGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(BOARD_GRID_SIDE_LENGTH) });
}
var maxColIndex = Game.ALL_ROWS.Max();
foreach (var col in Enumerable.Range(0, maxColIndex))
{
boardGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(BOARD_GRID_SIDE_WIDTH) });
}
// ...
}
Лучше всего было бы использовать ViewBox, предполагая, что на доске, которую вы хотите нарисовать, есть постоянное количество строк / столбцов.
Звуковое решение состоит в том, чтобы разделить вашу страницу так, чтобы boardGrid
занимает 2/3 экрана, остальная часть вашего контента (кнопки, таймер, табло...) в другой трети.
Во-вторых, заключите его внутрь Viewbox
элемент, так что размеры платы пересчитываются при переходе в разные режимы просмотра (Полный, Портрет, Защелкивающийся, Заполненный)
Наконец, убедитесь, что страница наследуется LayoutAwarePage
вместо Page
так что он корректно обрабатывает изменения режимов просмотра
Вот грубый макет:
<common:LayoutAwarePage
xmlns:UI="using:Microsoft.Advertising.WinRT.UI"
x:Class="ApexKT.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp"
xmlns:common="using:MyApp.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:snaps="http://schemas.microsoft.com/netfx/2007/xaml/presentation"
mc:Ignorable="d" >
<Grid x:Name="bigGrid">
<StackPanel Orientation="Horizontal">
<StackPanel x:Name="OneThird">
<TextBlock x:Name="ScoreBoard" Text="Score:" />
<Button x:Name="Button1" Content="Button 1" Click="" />
</StackPanel>
<Viewbox x:Name="TwoThirds">
<Viewbox.Transitions>
<TransitionCollection>
<ContentThemeTransition />
</TransitionCollection>
</Viewbox.Transitions>
<Grid x:Name="boardGrid"><!-- insert row and column definitions here, or hard code them --></Grid>
</Viewbox>
</StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<VisualState x:Name="Snapped" />
<VisualState x:Name="FullScreenPortrait" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
`