Orientace zařízení

Ukázka stažení Stažení ukázky

Je důležité vzít v úvahu, jak se bude vaše aplikace používat a jak se dá přizpůsobovat orientace na šířku pro zlepšení uživatelského prostředí. Jednotlivá rozložení je možné navrhnout tak, aby vyhovovala více orientací a co nejlépe využívají dostupný prostor. Na úrovni aplikace lze otočení zakázat nebo povolit.

Řízení orientace

Při použití nástroje Xamarin.Forms je podporovaná metoda řízení orientace zařízení použita k použití nastavení pro jednotlivé projekty.

iOS

V systému iOS je orientace zařízení nakonfigurovaná pro aplikace, které používají soubor info. plist . Pomocí možností IDE v horní části tohoto dokumentu vyberte, které pokyny chcete zobrazit:

v Visual Studio otevřete projekt iOS a otevřete Info. plist. soubor se otevře na panelu konfigurace, počínaje iPhone kartě informace o nasazení:

informace o nasazení iPhone v Visual Studio

Android

Chcete-li řídit orientaci v Androidu, otevřete MainActivity. cs a nastavte orientaci pomocí atributu upravení třídy:

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 zadání orientace:

  • Na šířku – vynutí orientaci orientace aplikace na šířku, bez ohledu na data ze senzorů.
  • Na výšku – vynutí orientaci orientace aplikace na výšku, bez ohledu na data ze senzorů.
  • Uživatel – způsobí, že se aplikace zobrazí pomocí upřednostňované orientace uživatele.
  • Na pozadí způsobí, že orientace aplikace bude stejná jako orientace aktivity za ní.
  • Senzor – způsobí, že se na základě senzoru určí orientace aplikace, i když uživatel zakázal automatické otočení.
  • SensorLandscape – způsobí, že aplikace bude používat orientaci na šířku při používání dat snímače ke změně směru, na který obrazovka směřuje (takže se obrazovka nezobrazuje tak, jak je dostupná).
  • SensorPortrait – způsobí, že aplikace bude používat orientaci na výšku a zároveň používá data ze senzorů ke změně směru, na který obrazovka směřuje (takže se obrazovka nezobrazuje tak, jak je umístěná).
  • ReverseLandscape – způsobí, že aplikace bude používat orientaci na šířku, která má opačný směr od obvyklého, takže se zobrazí jako "nefunkční".
  • ReversePortrait – způsobí, že aplikace bude používat orientaci na výšku, která má opačný směr, a to tak, aby se zobrazila v provozu.
  • FullSensor – způsobí, že aplikace bude spoléhat na data ze senzorů, aby vybrala správnou orientaci (z možného 4).
  • FullUser – způsobí, že aplikace použije předvolby orientace uživatele. Pokud je povolené automatické otočení, dají se použít všechny 4 orientace.
  • UserLandscape[nepodporované] způsobí, že aplikace bude používat orientaci na šířku, pokud uživatel nemá povolené automatické otočení. v takovém případě se k určení orientace použije senzor. Tato možnost zruší kompilaci.
  • UserPortrait[nepodporované] způsobí, že aplikace bude používat orientaci na výšku, pokud uživatel nemá povolené automatické otočení. v takovém případě se k určení orientace použije senzor. Tato možnost zruší kompilaci.
  • Uzamčené[Nepodporováno] způsobí, že aplikace bude používat orientaci obrazovky bez ohledu na to, kde je spuštěná, a to bez reakce na změny fyzické orientace zařízení. Tato možnost zruší kompilaci.

Všimněte si, že nativní rozhraní API pro Android poskytují velkou kontrolu nad správou orientace, včetně možností, které explicitně odporují vyjádřeným požadavkům uživatele.

platforma Universal Windows

v Univerzální platforma Windows (UWP) jsou v souboru Package. appxmanifest nastavena podporovaná orientace. Otevřením manifestu se zobrazí panel konfigurace, kde můžete vybrat podporované orientace.

Reakce na změny v orientaci

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

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

Alternativně je možné přepsat OnSizeAllocated metodu na a Page vložením libovolné logiky změny rozložení tam. OnSizeAllocatedMetoda je volána vždy, když Page je přidělena nová velikost, což nastane při každém otočení 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 se tento krok nepovede, nebudete mít za následek nefunkční stránku.

Všimněte si, že OnSizeAllocated metoda může být volána několikrát při otočení zařízení. Změna rozložení pokaždé, když se wasteful prostředky a může vést k blikání. Zvažte použití proměnné instance v rámci stránky a sledujte, zda je orientace na šířku nebo na výšku, a překreslete 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
    }
}

Jakmile se zjistí Změna orientace zařízení, můžete chtít přidat nebo odebrat další zobrazení do nebo z uživatelského rozhraní a reagovat tak na změnu v dostupném prostoru. Představte si třeba vestavěnou kalkulačku na výšku jednotlivých platforem:

Aplikace kalkulačky na výšku

a na šířku:

Aplikace kalkulačky na šířku

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

Rozložení reakce

Je možné navrhnout rozhraní pomocí integrovaných rozložení, aby se při otočení zařízení plynule překrývaly. Při navrhování rozhraní, která se budou i nadále používat při reakci na změny v orientaci, zvažte následující obecná pravidla:

  • Věnujte pozornost poměrům – změny v orientaci můžou způsobit problémy, když se v souvislosti s poměry k poměrům provedou určité předpoklady. Například zobrazení, které by mělo dostatek místa v 1/3 svislého prostoru obrazovky na výšku, se nemusí vejít do 1/3 svislého prostoru na šířku.
  • Buďte opatrní s absolutními hodnotami (v pixelech), které dávají smysl na výšku, nemusí mít smysl na šířku. Pokud jsou nezbytné absolutní hodnoty, použijte vnořené rozložení k izolaci jejich dopadu. Například by bylo rozumné použít absolutní hodnoty v TableViewItemTemplate případě, kdy má šablona položky 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é postupy. Zbývající část tohoto průvodce vám vysvětlí konkrétní příklady citlivostní zobrazení pomocí každého primárního rozložení v Xamarin.Forms .

Poznámka

Pro přehlednost jsou v následujících oddílech ukázány, jak implementovat reakce na rozložení s použitím pouze jednoho typu Layout po dobu. V praxi je často jednodušší je kombinovat Layout s cílem dosáhnout požadovaného rozložení pomocí jednodušší nebo nejužitečnějšího Layout pro jednotlivé komponenty.

StackLayout

Vezměte v úvahu následující aplikaci, která se zobrazuje na výšku:

Snímek obrazovky ukazuje, že aplikace Photo StackLayout je na výšku.

a na šířku:

Snímek obrazovky ukazuje, že aplikace Photo StackLayout na šířku.

To je provedeno pomocí následujícího kódu 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é jazyky C# slouží ke změně orientace na outerStack 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;
        }
    }
}

Poznačte si následující údaje:

  • outerStack se upraví tak, aby obsahovalo image a ovládací prvky jako vodorovný nebo svislý zásobník v závislosti na orientaci, abyste mohli nejlépe využít dostupného místa.

AbsoluteLayout

Vezměte v úvahu následující aplikaci, která se zobrazuje na výšku:

Snímek obrazovky ukazuje, že aplikace Photo AbsoluteLayout je na výšku.

a na šířku:

Snímek obrazovky ukazuje, že aplikace Photo AbsoluteLayout na šířku.

To je provedeno pomocí následujícího kódu 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>

Poznačte si následující údaje:

  • Z důvodu způsobu, jakým se stránka nastavila, není nutné, aby kód procedurálního postupu zavedl odezvu.
  • ScrollViewSlouží k povolení viditelného popisku, i když je výška obrazovky menší než součet pevné výšky tlačítek a obrázku.

RelativeLayout

Vezměte v úvahu následující aplikaci, která se zobrazuje na výšku:

Snímek obrazovky ukazuje, že aplikace Photo RelativeLayout je na výšku.

a na šířku:

Snímek obrazovky znázorňuje Objekt RelativeLayout aplikace fotografií v oblasti Na šířku

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

Poznačte si následující údaje:

  • Vzhledem ke způsobu rozložení stránky není potřeba, aby procedurální kód zavádět rychlost odezvy.
  • Používá se 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 ScrollView obrázku.

Mřížka

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

Snímek obrazovky znázorňuje Photo Application Grid na výšku

a na šířku:

Snímek obrazovky s mřížkou Photo Application Grid v oblasti Na šířku

To se provádí pomocí následujícího kódu 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 rotace:

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

Poznačte si následující údaje:

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