Orientace zařízení

Download Sample Stažení ukázky

Je důležité zvážit, jak se bude vaše aplikace používat a jak lze začlenit orientaci na šířku, aby se zlepšilo uživatelské prostředí. Jednotlivá rozložení lze navrhnout tak, aby vyhovovala více orientací a co nejlépe využila dostupné místo. Na úrovni aplikace může být rotace zakázaná nebo povolená.

Řízení orientace

Při použití Xamarin.Formsje podporovaná metoda řízení orientace zařízení použít nastavení pro každý jednotlivý projekt.

iOS

V iOSu je orientace zařízení nakonfigurovaná pro aplikace používající soubor Info.plist . Pomocí možností integrovaného vývojového prostředí (IDE) v horní části tohoto dokumentu vyberte, které pokyny chcete zobrazit:

V sadě Visual Studio otevřete projekt iOS a otevřete Soubor Info.plist. Soubor se otevře na konfiguračním panelu počínaje kartou i Telefon Informace o nasazení:

iPhone Deployment Info in Visual Studio

Android

Pokud chcete řídit orientaci v Androidu, otevřete MainActivity.cs a nastavte orientaci pomocí atributu dekorující MainActivity třídu:

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 podporuje několik možností pro určení orientace:

  • Na šířku – vynutí orientaci aplikace na šířku bez ohledu na data ze senzorů.
  • Na výšku – vynutí orientaci aplikace na výšku bez ohledu na data snímače.
  • Uživatel – způsobí, že se aplikace zobrazí s použitím preferované orientace uživatele.
  • Za – způsobí, že orientace aplikace bude stejná jako orientace aktivity za ní.
  • Senzor – způsobí, že senzor určí orientaci aplikace, i když uživatel zakázal automatické otáčení.
  • SensorLandscape – způsobí, že aplikace použije orientaci na šířku při použití dat ze snímačů ke změně směru zobrazení obrazovky (takže se obrazovka nezobrazuje jako vzhůru nohama).
  • SensorPortrait – způsobí, že aplikace použije orientaci na výšku při změně směru zobrazení obrazovky (aby se obrazovka nezobradřila vzhůru nohama).
  • ReverseLandscape – způsobí, že aplikace použije orientaci na šířku, směrem k opačnému směru než obvykle, takže se zobrazí "vzhůru nohama".
  • ReversePortrait – způsobí, že aplikace použije orientaci na výšku, směrem k opačnému směru než obvykle, takže se zobrazí "vzhůru nohama".
  • FullSensor – způsobí, že aplikace bude spoléhat na data snímačů, aby vybrali správnou orientaci (mimo možnou 4).
  • FullUser – způsobí, že aplikace použije předvolby orientace uživatele. Pokud je zapnutá automatická rotace, můžete použít všechny 4 orientace.
  • UserLandscape[Nepodporováno] způsobí, že aplikace použije orientaci na šířku, pokud uživatel nemá povolenou automatickou rotaci, v takovém případě použije senzor k určení orientace. Tato možnost přeruší kompilaci.
  • UserPortrait[Nepodporováno] způsobí, že aplikace použije orientaci na výšku, pokud uživatel nemá povolenou automatickou rotaci, v takovém případě použije senzor k určení orientace. Tato možnost přeruší kompilaci.
  • Uzamčeno[Nepodporováno] způsobí, že aplikace použije orientaci obrazovky bez ohledu na to, co je při spuštění, aniž by reagovala na změny ve fyzické orientaci zařízení. Tato možnost přeruší kompilaci.

Mějte na paměti, že nativní rozhraní API pro Android poskytují velkou kontrolu nad tím, jak se spravuje orientace, včetně možností, které explicitně odporují vyjádřeným předvolbám uživatele.

Univerzální platforma Windows

V Univerzální platforma Windows (UPW) jsou podporované orientace nastavené v souboru Package.appxmanifest. Otevření manifestu zobrazí konfigurační panel, kde je možné vybrat podporované orientace.

Reakce na změny v orientaci

Xamarin.Forms nenabízí žádné nativní události pro upozorňování aplikace na změny orientace ve sdíleném kódu. Xamarin.Essentials Obsahuje však třídu [DeviceDisplay], která poskytuje oznámení o změnách orientace.

Chcete-li zjistit orientaci bez Xamarin.Essentials, monitorujte SizeChanged událost Page, která se aktivuje, když je šířka nebo výška Page změn. Pokud je šířka Page větší než výška, zařízení je v režimu na šířku. Další informace naleznete v tématu Zobrazení obrázku na základě orientace obrazovky.

Alternativně je možné přepsat metodu OnSizeAllocated na , vložit do ní libovolnou logiku Pagezměny rozložení. Tato OnSizeAllocated metoda se volá vždy, když Page je přidělena nová velikost, ke které dochází při každé obměně zařízení. Všimněte si, že základní implementace OnSizeAllocated provádí důležité funkce rozložení, takže je důležité volat základní implementaci v přepsání:

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

Pokud tento krok neučiníte, dojde k nefunkční stránce.

Všimněte si, že OnSizeAllocated metoda se může volat mnohokrát, když se zařízení otočí. Pokaždé, když změníte rozložení, je plýtvání prostředky a může to vést k blikání. Zvažte použití proměnné instance na stránce ke sledování, jestli je orientace na šířku nebo na výšku, a překreslit pouze v případě, že dojde ke změně:

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
    }
}

Po zjištění změny orientace zařízení můžete chtít přidat nebo odebrat další zobrazení do a z uživatelského rozhraní, abyste mohli reagovat na změnu v dostupném prostoru. Představte si například integrovanou kalkulačku na jednotlivých platformách na výšku:

Calculator Application in Portrait

a na šířku:

Calculator Application in Landscape

Všimněte si, že aplikace využívají dostupné místo přidáním dalších funkcí na šířku.

Responzivní rozložení

Rozhraní je možné navrhnout pomocí předdefinovaných rozložení tak, aby při otáčení zařízení plynule přecházení. Při navrhování rozhraní, která budou při reagování na změny v orientaci nadále atraktivní, zvažte následující obecná pravidla:

  • Věnujte pozornost poměrům – změny v orientaci můžou způsobit problémy v případě, že jsou provedeny určité předpoklady s ohledem na poměry. Například pohled, který by měl dostatek místa ve 1/3 svislém prostoru obrazovky na výšku, se nemusí vejít do 1/3 svislého prostoru na šířku.
  • Buďte opatrní s absolutními hodnotami – absolutními (pixelovými) hodnotami, které dávají smysl na výšku, nemusí dávat smysl v krajině. Pokud jsou nezbytné absolutní hodnoty, izolujte jejich dopad pomocí vnořených rozložení. Bylo by například vhodné použít absolutní hodnoty v TableViewItemTemplate případě, že šablona položky má zaručenou jednotnou výšku.

Výše uvedená pravidla platí také při implementaci rozhraní pro více velikostí obrazovky a obecně se považují za osvědčený postup. Zbytek tohoto průvodce vysvětluje konkrétní příklady responzivních rozložení pomocí každého z primárních rozložení v Xamarin.Forms.

Poznámka:

Následující části ukazují, jak implementovat responzivní rozložení pomocí jednoho typu Layout najednou. V praxi je často jednodušší kombinovat Layouts dosažením požadovaného rozložení pomocí jednodušší nebo nejintuitivnější Layout pro každou komponentu.

StackLayout

Představte si následující aplikaci zobrazenou na výšku:

Screenshot shows Photo Application StackLayout in Portrait.

a na šířku:

Screenshot shows Photo Application StackLayout in Landscape.

To se provádí pomocí následujícího 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>

Některá jazyka C# slouží ke změně orientace outerStack na základě orientace zařízení:

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;
        }
    }
}

Je potřeba upozornit na následující:

  • outerStack se upraví tak, aby obrázek a ovládací prvky byly prezentovány jako vodorovný nebo svislý zásobník v závislosti na orientaci, aby bylo možné co nejlépe využít dostupné místo.

AbsoluteLayout

Představte si následující aplikaci zobrazenou na výšku:

Screenshot shows Photo Application AbsoluteLayout in Portrait.

a na šířku:

Screenshot shows Photo Application AbsoluteLayout in Landscape.

To se provádí pomocí následujícího 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>

Je potřeba upozornit na následující:

  • Vzhledem ke způsobu, jakým byla stránka rozložena, není nutné, aby procedurální kód zavedl rychlost odezvy.
  • Slouží ScrollView k tomu, aby byl popisek viditelný i v případě, že výška obrazovky je menší než součet pevných výšek tlačítek a obrázku.

RelativeLayout

Představte si následující aplikaci zobrazenou na výšku:

Screenshot shows Photo Application RelativeLayout in Portrait.

a na šířku:

Screenshot shows Photo Application RelativeLayout in Landscape.

To se provádí pomocí následujícího 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>

Je potřeba upozornit na následující:

  • Vzhledem ke způsobu, jakým byla stránka rozložena, není nutné, aby procedurální kód zavedl rychlost odezvy.
  • Slouží ScrollView k tomu, aby byl popisek viditelný i v případě, že výška obrazovky je menší než součet pevných výšek tlačítek a obrázku.

Mřížka

Představte si následující aplikaci zobrazenou na výšku:

Screenshot shows Photo Application Grid in Portrait.

a na šířku:

Screenshot shows Photo Application Grid in Landscape.

To se provádí pomocí následujícího 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>

Spolu s následujícím procedurálním kódem pro zpracování změn obměně:

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);
        }
    }
}

Je potřeba upozornit na následující:

  • Vzhledem ke způsobu rozložení stránky existuje metoda, jak změnit umístění mřížky ovládacích prvků.