Ориентация устройстваDevice Orientation

Загрузить образец загрузить примерDownload Sample Download the sample

Важно учитывать, как будет использоваться ваше приложение и как можно встроить альбомную ориентацию, чтобы улучшить взаимодействие с пользователем.It is important to consider how your application will be used and how landscape orientation can be incorporated to improve the user experience. Отдельные макеты можно разрабатывать для поддержки нескольких ориентаций и лучше использовать доступное пространство.Individual layouts can be designed to accommodate multiple orientations and best use the available space. На уровне приложения поворот может быть отключен или включен.At the application level, rotation can be disabled or enabled.

Управление ориентациейControlling Orientation

При использовании Xamarin.Forms поддерживаемым методом управления ориентацией устройства является использование параметров каждого отдельного проекта.When using Xamarin.Forms, the supported method of controlling device orientation is to use the settings for each individual project.

iOSiOS

В iOS Ориентация устройства настраивается для приложений, использующих файл info. plist .On iOS, device orientation is configured for applications using the Info.plist file. Используйте параметры интегрированной среды разработки в верхней части этого документа, чтобы выбрать, какие инструкции вы хотите увидеть:Use the IDE options at the top of this document to select which instructions you'd like to see:

В Visual Studio откройте проект iOS и откройте info. plist.In Visual Studio, open the iOS project and open Info.plist. Файл откроется на панели конфигурации, начиная со вкладки сведения о развертывании iPhone:The file will open into a configuration panel, starting with the iPhone Deployment Info tab:

Сведения о развертывании iPhone в Visual Studio

AndroidAndroid

Чтобы управлять ориентацией на Android, откройте MainActivity.CS и задайте ориентацию с помощью атрибута, определяющего MainActivity класс:To control the orientation on Android, open MainActivity.cs and set the orientation using the attribute decorating the MainActivity class:

namespace MyRotatingApp.Droid
{
    [Activity (Label = "MyRotatingApp.Droid", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, ScreenOrientation = ScreenOrientation.Landscape)] //This is what controls orientation
    public class MainActivity : FormsAppCompatActivity
    {
        protected override void OnCreate (Bundle bundle)
...

Xamarin. Android поддерживает несколько параметров для указания ориентации:Xamarin.Android supports several options for specifying orientation:

  • Альбомная ориентация – заставляет приложение располагаться в альбомной ориентации независимо от данных датчика.Landscape – forces the application orientation to be landscape, regardless of sensor data.
  • Книжная ориентация – заставляет приложение располагаться в книжной ориентации независимо от данных датчика.Portrait – forces the application orientation to be portrait, regardless of sensor data.
  • Пользователь – приводит к тому, что приложение будет представлено с использованием предпочтительной ориентации пользователя.User – causes the application to be presented using the user's preferred orientation.
  • Позади – Указывает, что ориентация приложения совпадает с ориентацией действия .Behind – causes the application's orientation to be the same as the orientation of the activity behind it.
  • Датчик – приводит к тому, что ориентация приложения определяется датчиком, даже если пользователь отключил автоматический поворот.Sensor – causes the application's orientation to be determined by the sensor, even if the user has disabled automatic rotation.
  • Сенсорландскапе – заставляет приложение использовать альбомную ориентацию при использовании данных датчика для изменения направления экрана (чтобы экран не отображался в виде переворачивания).SensorLandscape – causes the application to use landscape orientation while using sensor data to change the direction the screen is facing (so that the screen isn't seen as upside down).
  • Сенсорпортраит – заставляет приложение использовать книжную ориентацию при использовании данных датчика для изменения направления экрана (чтобы экран не отображался в виде переворачивания).SensorPortrait – causes the application to use portrait orientation while using sensor data to change the direction the screen is facing (so that the screen isn't seen as upside down).
  • Реверселандскапе – заставляет приложение использовать альбомную ориентацию, направленную в противоположное направление от обычного, чтобы она отображалась «сверху вниз».ReverseLandscape – causes the application to use landscape orientation, facing the opposite direction from usual, so as to appear "upside down."
  • Реверсепортраит – заставляет приложение использовать книжную ориентацию, направленную на противоположное направление от обычного, чтобы она отображалась как "перевернутая".ReversePortrait – causes the application to use portrait orientation, facing the opposite direction from usual, so as to appear "upside down."
  • Фуллсенсор – заставляет приложение полагаться на данные датчика, чтобы выбрать правильную ориентацию (из возможных 4).FullSensor – causes the application to rely on sensor data to select the correct orientation (out of the possible 4).
  • Фуллусер – заставляет приложение использовать предпочтения ориентации пользователя.FullUser – causes the application to use the user's orientation preferences. Если включен автоматический поворот, можно использовать все 4 ориентации.If automatic rotation is enabled, then all 4 orientations can be used.
  • Усерландскапе – _ [ Не поддерживается ] _ , если в приложении используется альбомная ориентация, если пользователь не включил автоматический поворот, в этом случае он будет использовать датчик для определения ориентации.UserLandscape[Not Supported] causes the application to use landscape orientation, unless the user has automatic rotation enabled, in which case it will use the sensor to determine orientation. Этот параметр приведет к нарушению компиляции.This option will break compilation.
  • Усерпортраит – _ [ Не поддерживается ] _ , если в приложении используется книжная ориентация, если только пользователь не включил автоматический поворот, в этом случае он будет использовать датчик для определения ориентации.UserPortrait[Not Supported] causes the application to use portrait orientation, unless the user has automatic rotation enabled, in which case it will use the sensor to determine orientation. Этот параметр приведет к нарушению компиляции.This option will break compilation.
  • Заблокировано – _ [ Не поддерживается ] _ указывает, что приложение будет использовать ориентацию экрана, независимо от того, где он запускается, без реагирования на изменения физической ориентации устройства.Locked[Not Supported] causes the application to use the screen orientation, whatever it is at launch, without responding to changes in the device's physical orientation. Этот параметр приведет к нарушению компиляции.This option will break compilation.

Обратите внимание, что собственные API-интерфейсы Android обеспечивают множество возможностей управления ориентацией, в том числе параметры, явно противоречащие параметрам, заданным пользователем.Note that the native Android APIs provide a lot of control over how orientation is managed, including options that explicitly contradict the user's expressed preferences.

Универсальная платформа WindowsUniversal Windows platform

В универсальная платформа Windows (UWP) поддерживаемые ориентации задаются в файле Package. appxmanifest .On the Universal Windows Platform (UWP), supported orientations are set in the Package.appxmanifest file. При открытии манифеста отображается панель конфигурации, где можно выбрать поддерживаемые ориентации.Opening the manifest will reveal a configuration panel where supported orientations can be selected.

Реагирование на изменения ориентацииReacting to Changes in Orientation

Xamarin.Formsне предоставляет собственные события для уведомления приложения об изменениях ориентации в общем коде. does not offer any native events for notifying your app of orientation changes in shared code. Однако Xamarin.Essentials содержит DeviceDisplay класс [], который предоставляет уведомления об изменении ориентации.However,Xamarin.Essentials contains a [DeviceDisplay] class that provides notifications of orientation changes.

Чтобы обнаружить ориентации без Xamarin.Essentials , следите за SizeChanged событием Page , которое срабатывает при изменении ширины или высоты Page изменений.To detect orientations without Xamarin.Essentials, monitor the SizeChanged event of the Page, which fires when either the width or height of the Page changes. Если ширина превышает Page высоту, устройство находится в альбомном режиме.When the width of the Page is greater than the height, the device is in landscape mode. Дополнительные сведения см. в разделе Отображение изображения на основе ориентации экрана.For more information, see Display an Image based on Screen Orientation.

Кроме того, можно переопределить OnSizeAllocated метод в Page , вставив в него любую логику изменения макета.Alternatively, it's possible to override the OnSizeAllocated method on a Page, inserting any layout change logic there. OnSizeAllocatedМетод вызывается каждый раз Page , когда выделяется новый размер, который происходит при каждом повороте устройства.The OnSizeAllocated method is called whenever a Page is allocated a new size, which happens whenever the device is rotated. Обратите внимание, что базовая реализация OnSizeAllocated выполняет важные функции макета, поэтому важно вызвать базовую реализацию в переопределении:Note that the base implementation of OnSizeAllocated performs important layout functions, so it is important to call the base implementation in the override:

protected override void OnSizeAllocated(double width, double height)
{
    base.OnSizeAllocated(width, height); //must be called
}

Если не выполнить этот шаг, это приведет к неработающей странице.Failure to take that step will result in a non-functioning page.

Обратите внимание, что OnSizeAllocated метод может вызываться много раз при вращении устройства.Note that the OnSizeAllocated method may be called many times when a device is rotated. Каждый раз при изменении макета используется непроизводительна ресурсов, что может привести к мерцанию.Changing your layout each time is wasteful of resources and can lead to flickering. Рекомендуется использовать переменную экземпляра на странице, чтобы определить ориентацию ориентации: альбомная или Книжная и только перерисовка при изменении.Consider using an instance variable within your page to track whether the orientation is in landscape or portrait, and only redraw when there is a change:

private double width = 0;
private double height = 0;

protected override void OnSizeAllocated(double width, double height)
{
    base.OnSizeAllocated(width, height); //must be called
    if (this.width != width || this.height != height)
    {
        this.width = width;
        this.height = height;
        //reconfigure layout
    }
}

После обнаружения изменения ориентации устройства может потребоваться добавить или удалить дополнительные представления в пользовательском интерфейсе, чтобы реагировать на изменения в доступном пространстве.Once a change in device orientation has been detected, you may want to add or remove additional views to/from your user interface to react to the change in available space. Например, рассмотрим встроенный калькулятор для каждой платформы в книжной ориентации:For example, consider the built-in calculator on each platform in portrait:

Приложение калькулятора в книжной ориентации

и альбомная ориентация:and landscape:

Приложение калькулятора в альбомной ориентации

Обратите внимание, что приложения используют преимущества доступного пространства путем добавления дополнительных функций в альбомной ориентации.Notice that the apps take advantage of the available space by adding more functionality in landscape.

Макет с откликомResponsive Layout

Можно разработать интерфейсы с помощью встроенных макетов, чтобы они были корректно перенесены при вращении устройства.It is possible to design interfaces using the built-in layouts so that they transition gracefully when the device is rotated. При проектировании интерфейсов, которые останутся привлекательными при ответе на изменения ориентации, учитывайте следующие общие правила.When designing interfaces that will continue to be appealing when responding to changes in orientation consider the following general rules:

  • Обратить внимание на соотношение – изменение ориентации может вызвать проблемы при определенных допущениях относительно соотношения.Pay attention to ratios – changes in orientation can cause problems when certain assumptions are made with regards to ratios. Например, представление, для которого в 1/3 вертикального пространства экрана в книжной ориентации может не уместиться в 1/3 по вертикали.For example, a view that would have plenty of space in 1/3 of the vertical space of a screen in portrait may not fit into 1/3 of the vertical space in landscape.
  • Будьте внимательны с абсолютными значениями – абсолютные (пиксельные) значения, имеющие смысл в книжной ориентации, могут не иметь смысла в альбомной ориентации.Be careful with absolute values – absolute (pixel) values that make sense in portrait may not make sense in landscape. Если требуются абсолютные значения, используйте вложенные макеты, чтобы изолировать их влияние.When absolute values are necessary, use nested layouts to isolate their impact. Например, разумно использовать абсолютные значения в, TableView ItemTemplate Если шаблон элемента имеет гарантированно одинаковую высоту.For example, it would be reasonable to use absolute values in a TableView ItemTemplate when the item template has a guaranteed uniform height.

Приведенные выше правила также применяются при реализации интерфейсов для нескольких размеров экрана и обычно считаются лучшим подходом.The above rules also apply when implementing interfaces for multiple screen sizes and are generally considered best-practice. Оставшаяся часть этого руководств поясняет конкретные примеры откликов, используя каждый из основных макетов в Xamarin.Forms .The rest of this guide will explain specific examples of responsive layouts using each of the primary layouts in Xamarin.Forms.

Примечание

Для ясности в следующих разделах показано, как реализовать макеты с быстрым реагированием, используя только один тип Layout за раз.For clarity, the following sections demonstrate how to implement responsive layouts using just one type of Layout at a time. На практике часто бывает проще смешивать Layout s для достижения желаемого макета, используя более простой или интуитивно понятный Layout для каждого компонента.In practice, it is often simpler to mix Layouts to achieve a desired layout using the simpler or most intuitive Layout for each component.

StackLayoutStackLayout

Рассмотрим следующее приложение, отображаемое в книжной ориентации:Consider the following application, displayed in portrait:

Фото приложение в книжной ориентации

и альбомная ориентация:and landscape:

Приложение для фотографий в альбомной ориентации

Это выполняется с помощью следующего кода XAML:That is accomplished with the following XAML:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResponsiveLayout.StackLayoutPageXaml"
Title="Stack Photo Editor - XAML">
    <ContentPage.Content>
        <StackLayout Spacing="10" Padding="5" Orientation="Vertical"
        x:Name="outerStack"> <!-- can change orientation to make responsive -->
            <ScrollView>
                <StackLayout Spacing="5" HorizontalOptions="FillAndExpand"
                    WidthRequest="1000">
                    <StackLayout Orientation="Horizontal">
                        <Label Text="Name: " WidthRequest="75"
                            HorizontalOptions="Start" />
                        <Entry Text="deer.jpg"
                            HorizontalOptions="FillAndExpand" />
                    </StackLayout>
                    <StackLayout Orientation="Horizontal">
                        <Label Text="Date: " WidthRequest="75"
                            HorizontalOptions="Start" />
                        <Entry Text="07/05/2015"
                            HorizontalOptions="FillAndExpand" />
                    </StackLayout>
                    <StackLayout Orientation="Horizontal">
                        <Label Text="Tags:" WidthRequest="75"
                            HorizontalOptions="Start" />
                        <Entry Text="deer, tiger"
                            HorizontalOptions="FillAndExpand" />
                    </StackLayout>
                    <StackLayout Orientation="Horizontal">
                        <Button Text="Save" HorizontalOptions="FillAndExpand" />
                    </StackLayout>
                </StackLayout>
            </ScrollView>
            <Image  Source="deer.jpg" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Для изменения ориентации outerStack на основе ориентации устройства используется несколько языков C#:Some C# is used to change the orientation of outerStack based on the orientation of the device:

protected override void OnSizeAllocated (double width, double height){
    base.OnSizeAllocated (width, height);
    if (width != this.width || height != this.height) {
        this.width = width;
        this.height = height;
        if (width > height) {
            outerStack.Orientation = StackOrientation.Horizontal;
        } else {
            outerStack.Orientation = StackOrientation.Vertical;
        }
    }
}

Следует отметить следующее.Note the following:

  • outerStackнастраивается для представления изображения и элементов управления в виде горизонтального или вертикального стека в зависимости от ориентации, что позволяет лучше использовать доступное пространство.outerStack is adjusted to present the image and controls as a horizontal or vertical stack depending on orientation, to best take advantage of the available space.

AbsoluteLayoutAbsoluteLayout

Рассмотрим следующее приложение, отображаемое в книжной ориентации:Consider the following application, displayed in portrait:

Фото приложение в книжной ориентации

и альбомная ориентация:and landscape:

Приложение для фотографий в альбомной ориентации

Это выполняется с помощью следующего кода XAML:That is accomplished with the following XAML:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResponsiveLayout.AbsoluteLayoutPageXaml"
Title="AbsoluteLayout - XAML" BackgroundImageSource="deer.jpg">
    <ContentPage.Content>
        <AbsoluteLayout>
            <ScrollView AbsoluteLayout.LayoutBounds="0,0,1,1"
                AbsoluteLayout.LayoutFlags="PositionProportional,SizeProportional">
                <AbsoluteLayout>
                    <Image Source="deer.jpg"
                        AbsoluteLayout.LayoutBounds=".5,0,300,300"
                        AbsoluteLayout.LayoutFlags="PositionProportional" />
                    <BoxView Color="#CC1A7019" AbsoluteLayout.LayoutBounds=".5
                        300,.7,50" AbsoluteLayout.LayoutFlags="XProportional
                        WidthProportional" />
                    <Label Text="deer.jpg" AbsoluteLayout.LayoutBounds = ".5
                        310,1, 50" AbsoluteLayout.LayoutFlags="XProportional
                        WidthProportional" HorizontalTextAlignment="Center" TextColor="White" />
                </AbsoluteLayout>
            </ScrollView>
            <Button Text="Previous" AbsoluteLayout.LayoutBounds="0,1,.5,60"
                AbsoluteLayout.LayoutFlags="PositionProportional
                    WidthProportional"
                BackgroundColor="White" TextColor="Green" BorderRadius="0" />
            <Button Text="Next" AbsoluteLayout.LayoutBounds="1,1,.5,60"
                AbsoluteLayout.LayoutFlags="PositionProportional
                    WidthProportional" BackgroundColor="White"
                    TextColor="Green" BorderRadius="0" />
        </AbsoluteLayout>
    </ContentPage.Content>
</ContentPage>

Следует отметить следующее.Note the following:

  • Из-за способа размещения страницы не требуется выполнять процедурный код, чтобы реализовать скорость реагирования.Because of the way the page has been laid out, there is no need for procedural code to introduce responsiveness.
  • Используется ScrollView для того, чтобы метка была видимой, даже если высота экрана меньше, чем сумма фиксированной высоты кнопок и изображения.The ScrollView is being used to allow the label to be visible even when the height of the screen is less than the sum of the fixed heights of the buttons and the image.

RelativeLayoutRelativeLayout

Рассмотрим следующее приложение, отображаемое в книжной ориентации:Consider the following application, displayed in portrait:

Фото приложение в книжной ориентации

и альбомная ориентация:and landscape:

Приложение для фотографий в альбомной ориентации

Это выполняется с помощью следующего кода XAML:That is accomplished with the following XAML:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResponsiveLayout.RelativeLayoutPageXaml"
Title="RelativeLayout - XAML"
BackgroundImageSource="deer.jpg">
    <ContentPage.Content>
        <RelativeLayout x:Name="outerLayout">
            <BoxView BackgroundColor="#AA1A7019"
                RelativeLayout.WidthConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Width,Factor=1}"
                RelativeLayout.HeightConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Height,Factor=1}"
                RelativeLayout.XConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Width,Factor=0,Constant=0}"
                RelativeLayout.YConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Height,Factor=0,Constant=0}" />
            <ScrollView
                RelativeLayout.WidthConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Width,Factor=1}"
                RelativeLayout.HeightConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Height,Factor=1,Constant=-60}"
                RelativeLayout.XConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Width,Factor=0,Constant=0}"
                RelativeLayout.YConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Height,Factor=0,Constant=0}">
                <RelativeLayout>
                    <Image Source="deer.jpg" x:Name="imageDeer"
                        RelativeLayout.WidthConstraint="{ConstraintExpression
                            Type=RelativeToParent,Property=Width,Factor=.8}"
                        RelativeLayout.XConstraint="{ConstraintExpression
                            Type=RelativeToParent,Property=Width,Factor=.1}"
                        RelativeLayout.YConstraint="{ConstraintExpression
                            Type=RelativeToParent,Property=Height,Factor=0,Constant=10}" />
                    <Label Text="deer.jpg" HorizontalTextAlignment="Center"
                        RelativeLayout.WidthConstraint="{ConstraintExpression
                            Type=RelativeToParent,Property=Width,Factor=1}"
                        RelativeLayout.HeightConstraint="{ConstraintExpression
                            Type=RelativeToParent,Property=Height,Factor=0,Constant=75}"
                        RelativeLayout.XConstraint="{ConstraintExpression
                            Type=RelativeToParent,Property=Width,Factor=0,Constant=0}"
                        RelativeLayout.YConstraint="{ConstraintExpression
                            Type=RelativeToView,ElementName=imageDeer,Property=Height,Factor=1,Constant=20}" />
                </RelativeLayout>

            </ScrollView>

            <Button Text="Previous" BackgroundColor="White" TextColor="Green" BorderRadius="0"
                RelativeLayout.YConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Height,Factor=1,Constant=-60}"
                RelativeLayout.XConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Width,Factor=0,Constant=0}"
                RelativeLayout.HeightConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Width,Factor=0,Constant=60}"
                RelativeLayout.WidthConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Width,Factor=.5}"
                 />
            <Button Text="Next" BackgroundColor="White" TextColor="Green" BorderRadius="0"
                RelativeLayout.XConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Width,Factor=.5}"
                RelativeLayout.YConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Height,Factor=1,Constant=-60}"
                RelativeLayout.HeightConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Width,Factor=0,Constant=60}"
                RelativeLayout.WidthConstraint="{ConstraintExpression
                    Type=RelativeToParent,Property=Width,Factor=.5}"
                />
        </RelativeLayout>
    </ContentPage.Content>
</ContentPage>

Следует отметить следующее.Note the following:

  • Из-за способа размещения страницы не требуется выполнять процедурный код, чтобы реализовать скорость реагирования.Because of the way the page has been laid out, there is no need for procedural code to introduce responsiveness.
  • Используется ScrollView для того, чтобы метка была видимой, даже если высота экрана меньше, чем сумма фиксированной высоты кнопок и изображения.The ScrollView is being used to allow the label to be visible even when the height of the screen is less than the sum of the fixed heights of the buttons and the image.

Макет GridGrid

Рассмотрим следующее приложение, отображаемое в книжной ориентации:Consider the following application, displayed in portrait:

Фото приложение в книжной ориентации

и альбомная ориентация:and landscape:

Приложение для фотографий в альбомной ориентации

Это выполняется с помощью следующего кода XAML:That is accomplished with the following XAML:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResponsiveLayout.GridPageXaml"
Title="Grid - XAML">
    <ContentPage.Content>
        <Grid x:Name="outerGrid">
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="60" />
            </Grid.RowDefinitions>
            <Grid x:Name="innerGrid" Grid.Row="0" Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Image Source="deer.jpg" Grid.Row="0" Grid.Column="0" HeightRequest="300" WidthRequest="300" />
                <Grid x:Name="controlsGrid" Grid.Row="0" Grid.Column="1" >
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Label Text="Name:" Grid.Row="0" Grid.Column="0" />
                    <Label Text="Date:" Grid.Row="1" Grid.Column="0" />
                    <Label Text="Tags:" Grid.Row="2" Grid.Column="0" />
                    <Entry Grid.Row="0" Grid.Column="1" />
                    <Entry Grid.Row="1" Grid.Column="1" />
                    <Entry Grid.Row="2" Grid.Column="1" />
                </Grid>
            </Grid>
            <Grid x:Name="buttonsGrid" Grid.Row="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Button Text="Previous" Grid.Column="0" />
                <Button Text="Save" Grid.Column="1" />
                <Button Text="Next" Grid.Column="2" />
            </Grid>
        </Grid>
    </ContentPage.Content>
</ContentPage>

А также приведенный ниже процедурный код для управления изменениями вращения.Along with the following procedural code to handle rotation changes:

private double width;
private double height;

protected override void OnSizeAllocated (double width, double height){
    base.OnSizeAllocated (width, height);
    if (width != this.width || height != this.height) {
        this.width = width;
        this.height = height;
        if (width > height) {
            innerGrid.RowDefinitions.Clear();
            innerGrid.ColumnDefinitions.Clear ();
            innerGrid.RowDefinitions.Add (new RowDefinition{ Height = new GridLength (1, GridUnitType.Star) });
            innerGrid.ColumnDefinitions.Add (new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) });
            innerGrid.ColumnDefinitions.Add (new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) });
            innerGrid.Children.Remove (controlsGrid);
            innerGrid.Children.Add (controlsGrid, 1, 0);
        } else {
            innerGrid.RowDefinitions.Clear();
            innerGrid.ColumnDefinitions.Clear ();
            innerGrid.ColumnDefinitions.Add (new ColumnDefinition{ Width = new GridLength (1, GridUnitType.Star) });
            innerGrid.RowDefinitions.Add (new RowDefinition { Height = new GridLength (1, GridUnitType.Auto) });
            innerGrid.RowDefinitions.Add (new RowDefinition { Height = new GridLength (1, GridUnitType.Star) });
            innerGrid.Children.Remove (controlsGrid);
            innerGrid.Children.Add (controlsGrid, 0, 1);
        }
    }
}

Следует отметить следующее.Note the following:

  • Из-за способа размещения страницы существует метод изменения расположения элементов управления в сетке.Because of the way the page has been laid out, there is a method to change the grid placement of the controls.