Zpracování otáčení
Toto téma popisuje, jak zpracovat změny orientace zařízení v Xamarin. Android. Popisuje, jak pracovat se systémem Android Resource System a automaticky načítat prostředky pro konkrétní orientaci zařízení a jak programově zpracovat změny orientace.
Přehled
Vzhledem k tomu, že mobilní zařízení jsou snadno otočená, je vestavěná rotace standardní funkce v Mobile operačních systémech. Android poskytuje sofistikovanou architekturu pro práci s rotací v aplikacích, ať už je uživatelské rozhraní vytvořené deklarativně v XML nebo programově v kódu. Při automatickém zpracování změn deklarativního rozložení na otočeném zařízení může aplikace těžit z těsné integrace se systémem prostředků Android. Pro programové rozložení je nutné zpracovat změny ručně. To umožňuje přesnější řízení za běhu, ale na úkor více práce pro vývojáře. Aplikace může také zvolit, že se má odhlásit z restartování aktivity a provést ruční kontrolu nad změnou orientace.
Tato příručka se zabývá následujícími tématy o orientaci:
Deklarativní otočení rozložení – způsob použití systému prostředků Android k vytváření aplikací pracujících s orientací, včetně toho, jak načíst rozložení i drawables pro konkrétní orientaci.
Programové otočení rozložení – způsob přidávání ovládacích prvků programově a postup ručního zpracování změn orientace.
Deklarativní zpracování otočení pomocí rozložení
Zahrnutím souborů do složek, které následují konvence pojmenování, Android při změně orientace automaticky načte příslušné soubory. Teď obsahuje podporu pro:
Rozložení prostředků – určení, které soubory rozložení jsou pro každou orientaci neploché.
Vykreslitelné prostředky – určení, které drawables se načítají pro každou orientaci.
Rozložení prostředků
Ve výchozím nastavení jsou soubory AXML (Android XML), které jsou součástí složky Resources/layout , používány pro vykreslování zobrazení aktivity. Prostředky této složky se používají pro orientaci na výšku i na šířku, pokud nejsou k dispozici žádné další prostředky rozložení určené pro použití na šířku. Vezměte v úvahu strukturu projektu vytvořenou výchozí šablonou projektu:
Tento projekt vytvoří jeden soubor Main. axml ve složce Resources/Layouts . Když OnCreate je volána metoda aktivity, vyrovná zobrazení definované v OnCreate které deklaruje tlačítko, jak je znázorněno v XML níže:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"/>
</LinearLayout>
Pokud je zařízení otočené na orientaci na šířku, OnCreate metoda aktivity je volána znovu a stejný OnCreate je plochý, jak je znázorněno na následujícím snímku obrazovky:
Orientation-Specific rozložení
Kromě složky rozložení (která má výchozí hodnotu na výšku a může být také explicitně pojmenována rozložení-port zahrnutím složky s názvem ), aplikace může definovat zobrazení, která potřebuje v případě potřeby na šířku, aniž by došlo ke změně kódu.
Předpokládejme, že hlavní soubor. axml obsahoval následující kód XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="This is portrait"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</RelativeLayout>
Pokud se do projektu přidá složka s názvem layout-pozemky, která obsahuje další hlavní soubor. axml , rozplochý vzhled teď bude mít za následek, že Android načte nově přidané hlavní. axml. Vezměte v úvahu verzi hlavního souboru . axml , který obsahuje následující kód (pro jednoduchost se tento kód XML podobá výchozí verzi kódu na výšku, ale používá jiný řetězec v ):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="This is landscape"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</RelativeLayout>
Spuštění tohoto kódu a otáčení zařízení z na výšku na šířku znázorňuje nové načtení XML, jak je znázorněno níže:
Nakreslené prostředky
Během rotace Android považuje nakreslené prostředky podobně jako rozložení prostředků. V takovém případě systém získá drawables z prostředků/kreslicích a prostředků/plochých složek, v uvedeném pořadí.
Řekněme například, že projekt obsahuje obrázek s názvem Monkey.png ve složce Resources/drawed , kde je na vykreslení odkazováno z v XML takto:
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/monkey"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
Pojďme dále předpokládat, že v části prostředky/vykreslitelné – půdaje obsažena odlišná verze Monkey.png . Stejně jako u souborů rozložení se při otočení zařízení vykreslí změny pro danou orientaci, jak je znázorněno níže:
Programové otočení při zpracování
Někdy definujeme rozložení v kódu. K tomu může dojít z nejrůznějších důvodů, včetně technických omezení, předvolbách pro vývojáře atd. Když přidáváme ovládací prvky programově, musí aplikace ručně přihlédnout k orientaci zařízení, která se automaticky zpracuje při používání prostředků XML.
Přidávání ovládacích prvků v kódu
Chcete-li přidat ovládací prvky programově, aplikace musí provést následující kroky:
- Vytvořte rozložení.
- Nastavte parametry rozložení.
- Vytvořte ovládací prvky.
- Nastavte parametry rozložení ovládacích prvků.
- Přidejte ovládací prvky do rozložení.
- Nastavte rozložení jako zobrazení obsahu.
Zvažte například uživatelské rozhraní sestávající z jednoho TextView ovládacího prvku, který je přidán do RelativeLayout , jak je znázorněno v následujícím kódu.
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// create a layout
var rl = new RelativeLayout (this);
// set layout parameters
var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
rl.LayoutParameters = layoutParams;
// create TextView control
var tv = new TextView (this);
// set TextView's LayoutParameters
tv.LayoutParameters = layoutParams;
tv.Text = "Programmatic layout";
// add TextView to the layout
rl.AddView (tv);
// set the layout as the content view
SetContentView (rl);
}
Tento kód vytvoří instanci RelativeLayout třídy a nastaví její LayoutParameters vlastnost. LayoutParamsTřída je způsob, jak zapouzdřit, jak jsou ovládací prvky umístěny opakovaně použitelným způsobem. Po vytvoření instance rozložení lze ovládací prvky vytvořit a přidat do ní. Ovládací prvky mají také LayoutParameters , jako TextView v tomto příkladu. Po TextView vytvoření je přidání do RelativeLayout a nastavení RelativeLayout jako výsledek zobrazení obsahu v aplikaci, která zobrazuje, TextView jak je znázorněno na následujícím obrázku:
Detekce orientace v kódu
Pokud se aplikace pokusí načíst jiné uživatelské rozhraní pro každou orientaci při OnCreate volání metody (k tomu dojde pokaždé, když je zařízení otočené), musí zjistit orientaci a pak načíst požadovaný kód uživatelského rozhraní. Android má třídu nazvanou WindowManager , která se dá použít k určení aktuálního otočení zařízení prostřednictvím WindowManager.DefaultDisplay.Rotation vlastnosti, jak je znázorněno níže:
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// create a layout
var rl = new RelativeLayout (this);
// set layout parameters
var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
rl.LayoutParameters = layoutParams;
// get the initial orientation
var surfaceOrientation = WindowManager.DefaultDisplay.Rotation;
// create layout based upon orientation
RelativeLayout.LayoutParams tvLayoutParams;
if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation == SurfaceOrientation.Rotation180) {
tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
} else {
tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
tvLayoutParams.LeftMargin = 100;
tvLayoutParams.TopMargin = 100;
}
// create TextView control
var tv = new TextView (this);
tv.LayoutParameters = tvLayoutParams;
tv.Text = "Programmatic layout";
// add TextView to the layout
rl.AddView (tv);
// set the layout as the content view
SetContentView (rl);
}
Tento kód nastaví, TextView aby byl umístěn 100 pixelů v levém horním rohu obrazovky a automaticky animován do nového rozložení při otočení na na šířku, jak je znázorněno zde:
Prevence restartování aktivity
Kromě manipulace všeho v OnCreate aplikaci může aplikace také zabránit restartování aktivity, když se změna orientace provádí nastavením ConfigurationChanges v následujícím ActivityAttribute příkladu:
[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
Když se teď zařízení otočí, aktivita se nerestartuje. Aby bylo možné ručně zpracovat změnu orientace v tomto případě, může aktivita přepsat OnConfigurationChanged metodu a určit orientaci z Configuration objektu, který je předaný, jako v nové implementaci následující aktivity:
[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
public class CodeLayoutActivity : Activity
{
TextView _tv;
RelativeLayout.LayoutParams _layoutParamsPortrait;
RelativeLayout.LayoutParams _layoutParamsLandscape;
protected override void OnCreate (Bundle bundle)
{
// create a layout
// set layout parameters
// get the initial orientation
// create portrait and landscape layout for the TextView
_layoutParamsPortrait = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
_layoutParamsLandscape = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
_layoutParamsLandscape.LeftMargin = 100;
_layoutParamsLandscape.TopMargin = 100;
_tv = new TextView (this);
if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation == SurfaceOrientation.Rotation180) {
_tv.LayoutParameters = _layoutParamsPortrait;
} else {
_tv.LayoutParameters = _layoutParamsLandscape;
}
_tv.Text = "Programmatic layout";
rl.AddView (_tv);
SetContentView (rl);
}
public override void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)
{
base.OnConfigurationChanged (newConfig);
if (newConfig.Orientation == Android.Content.Res.Orientation.Portrait) {
_tv.LayoutParameters = _layoutParamsPortrait;
_tv.Text = "Changed to portrait";
} else if (newConfig.Orientation == Android.Content.Res.Orientation.Landscape) {
_tv.LayoutParameters = _layoutParamsLandscape;
_tv.Text = "Changed to landscape";
}
}
}
Zde TextView's jsou inicializovány parametry rozložení pro orientaci na šířku i na výšku. Proměnné třídy uchovávají parametry společně s TextView sebou samým, protože aktivita nebude znovu vytvořena při změně orientace. Kód stále používá surfaceOrientartion v v OnCreate k nastavení počátečního rozložení pro TextView . Potom OnConfigurationChanged zpracuje všechny následné změny rozložení.
Když aplikaci spustíme, Android načte změny uživatelského rozhraní, protože dojde k rotaci zařízení a nerestartuje aktivitu.
Prevence restartování aktivity pro deklarativní rozložení
Restartování aktivity způsobené otočením zařízení může být také znemožněno, pokud definujete rozložení v jazyce XML. Tento postup můžeme použít například v případě, že chceme zabránit restartování aktivity (z důvodů výkonu, případně) a nepotřebujeme načíst nové prostředky pro různé orientace.
Provedeme to stejným způsobem, jaký používáme v programovém rozložení. Jednoduše nastavili ConfigurationChanges v ActivityAttribute , stejně jako v CodeLayoutActivity minulosti. Jakýkoli kód, který musí být spuštěn pro změnu orientace, lze v metodě znovu implementovat OnConfigurationChanged .
Údržba stavu během změn orientace
Bez ohledu na to, jestli se rotace zpracovává deklarativně nebo programově, musí všechny aplikace pro Android implementovat stejné techniky pro správu stavu, když se změní orientace zařízení. Stav správy je důležitý, protože systém při otočení zařízení s Androidem restartuje běžící aktivitu. V systému Android to usnadňuje načítání alternativních prostředků, jako jsou rozložení a drawables, které jsou navržené speciálně pro konkrétní orientaci. Když se restartuje, aktivita ztratí jakýkoliv přechodný stav, který může být uložený v proměnných lokální třídy. Proto je-li aktivita u aktivity nastavena na hodnotu, musí uchovávat svůj stav na úrovni aplikace. Aplikace potřebuje zpracovat ukládání a obnovování všech stavů aplikace, které chce zachovat v rámci změny orientace.
Další informace o trvalém stavu v Androidu najdete v průvodci životního cyklu aktivit .
Souhrn
Tento článek pojednává o použití integrovaných funkcí Androidu pro práci s rotací. Nejprve se vysvětluje, jak používat systém prostředků Android k vytváření aplikací podporujících orientaci. Pak se zobrazí postup, jak přidat ovládací prvky v kódu a jak ručně zpracovat změny orientace.





