Verarbeiten der Drehung

In diesem Thema wird beschrieben, wie Sie Änderungen an der Geräteausrichtung in Xamarin.Android behandeln. Es wird erläutert, wie Sie mit dem Android-Ressourcensystem arbeiten, um Ressourcen für eine bestimmte Geräteausrichtung automatisch zu laden, und wie Sie Ausrichtungsänderungen programmgesteuert behandeln.

Übersicht

Da mobile Geräte leicht gedreht werden können, ist die integrierte Drehung ein Standardfeature in mobilen Betriebssysteme. Android bietet ein ausgereiftes Framework für den Umgang mit Der Rotation innerhalb von Anwendungen, unabhängig davon, ob die Benutzeroberfläche deklarativ in XML oder programmgesteuert im Code erstellt wird. Bei der automatischen Verarbeitung deklarativer Layoutänderungen auf einem gedrehten Gerät kann eine Anwendung von der engen Integration in das Android-Ressourcensystem profitieren. Für das programmgesteuerte Layout müssen Änderungen manuell behandelt werden. Dies ermöglicht eine präzisere Steuerung zur Laufzeit, aber auf Kosten von mehr Arbeit für den Entwickler. Eine Anwendung kann sich auch dafür entscheiden, den Aktivitätsneustart zu deaktivieren und die manuelle Kontrolle über Ausrichtungsänderungen zu übernehmen.

In diesem Leitfaden werden die folgenden Orientierungsthemen untersucht:

  • Deklarative Layoutrotation : Hier erfahren Sie, wie Sie das Android-Ressourcensystem verwenden, um ausrichtungsfähige Anwendungen zu erstellen, einschließlich des Ladens von Layouts und Zeichnungswerten für bestimmte Ausrichtungen.

  • Programmgesteuerte Layoutdrehung : Programmgesteuertes Hinzufügen von Steuerelementen sowie manuelles Behandeln von Ausrichtungsänderungen.

Deklaratives Behandeln von Drehungen mit Layouts

Durch das Einschließen von Dateien in Ordnern, die Namenskonventionen folgen, lädt Android automatisch die entsprechenden Dateien, wenn sich die Ausrichtung ändert. Unter anderem werden folgende Elemente unterstützt:

  • Layoutressourcen : Geben Sie an, welche Layoutdateien für jede Ausrichtung aufgebläht werden.

  • Drawable Resources : Gibt an, welche Drawables für jede Ausrichtung geladen werden.

Layoutressourcen

Standardmäßig werden Android XML-Dateien (AXML), die im Ordner "Ressourcen/Layout " enthalten sind, zum Rendern von Ansichten für eine Aktivität verwendet. Die Ressourcen dieses Ordners werden sowohl für die Ausrichtung im Hoch- als auch im Querformat verwendet, wenn keine zusätzlichen Layoutressourcen speziell für das Querformat bereitgestellt werden. Betrachten Sie die Projektstruktur, die von der Standardprojektvorlage erstellt wurde:

Standardprojektvorlagenstruktur

Dieses Projekt erstellt eine einzelne Main.axml-Datei im Ordner Resources/layout . Wenn die -Methode der OnCreate Aktivität aufgerufen wird, wird die in Main.axml definierte Ansicht aufgeblasen, die eine Schaltfläche deklariert, wie im folgenden XML-Code gezeigt:

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

Wenn das Gerät im Querformat gedreht wird, wird die Activity-Methode OnCreate erneut aufgerufen, und dieselbe Main.axml-Datei wird aufgeblasen, wie im folgenden Screenshot gezeigt:

Gleicher Bildschirm, aber im Querformat

Orientation-Specific Layouts

Zusätzlich zum Layoutordner (der standardmäßig hochformatiert ist und auch explizit layout-port benannt werden kann, indem ein Ordner mit dem Namen layout-landeingeschlossen wird), kann eine Anwendung die benötigten Ansichten im Querformat ohne Codeänderungen definieren.

Angenommen, die Datei Main.axml enthielt den folgenden XML-Code:

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

Wenn dem Projekt ein Ordner mit dem Namen layout-land hinzugefügt wird, der eine zusätzliche Main.axml-Datei enthält, führt das Vergrößern des Layouts im Querformat nun dazu, dass Android die neu hinzugefügte Datei Main.axml lädt. Betrachten Sie die Querformatversion der Datei Main.axml , die den folgenden Code enthält (der Einfachheit halber ähnelt diese XML der Standardversion im Hochformat des Codes, verwendet jedoch eine andere Zeichenfolge im TextView):

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

Wenn Sie diesen Code ausführen und das Gerät vom Hochformat in das Querformat rotieren, wird das neue XML-Laden veranschaulicht, wie unten gezeigt:

Screenshots im Hoch- und Querformat beim Drucken des Hochformatmodus

Drawable Resources

Während der Drehung behandelt Android ziehbare Ressourcen ähnlich wie Layoutressourcen. In diesem Fall ruft das System die Drawables aus den Ordnern Resources/drawable und Resources/drawable-land ab.

Angenommen, das Projekt enthält ein Bild mit dem Namen Monkey.png im Ordner Resources/drawable , wobei auf das zeichenbare in XML ImageView wie folgt verwiesen wird:

<ImageView
  android:layout_height="wrap_content"
  android:layout_width="wrap_content"
  android:src="@drawable/monkey"
  android:layout_centerVertical="true"
  android:layout_centerHorizontal="true" />

Nehmen wir weiter an, dass eine andere Version von Monkey.png unter Resources/drawable-land enthalten ist. Genau wie bei den Layoutdateien ändert sich, wenn das Gerät gedreht wird, das Zeichnungsbare für die angegebene Ausrichtung, wie unten gezeigt:

Verschiedene Versionen von Monkey.png im Hoch- und Querformat angezeigt

Programmgesteuertes Behandeln der Drehung

Manchmal definieren wir Layouts im Code. Dies kann aus einer Vielzahl von Gründen geschehen, z. B. aus technischen Einschränkungen, Entwicklerpräferenzen usw. Wenn wir Steuerelemente programmgesteuert hinzufügen, muss eine Anwendung die Geräteausrichtung manuell berücksichtigen, was automatisch behandelt wird, wenn wir XML-Ressourcen verwenden.

Hinzufügen von Steuerelementen im Code

Um Steuerelemente programmgesteuert hinzuzufügen, muss eine Anwendung die folgenden Schritte ausführen:

  • Erstellen Sie ein Layout.
  • Legen Sie Layoutparameter fest.
  • Erstellen sie Steuerelemente.
  • Legen Sie Steuerelementlayoutparameter fest.
  • Fügen Sie dem Layout Steuerelemente hinzu.
  • Legen Sie das Layout als Inhaltsansicht fest.

Betrachten Sie beispielsweise eine Benutzeroberfläche, die aus einem einzelnen TextView Steuerelement besteht, das einem RelativeLayouthinzugefügt wird, wie im folgenden Code gezeigt.

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

Dieser Code erstellt eine instance einer RelativeLayout Klasse und legt deren LayoutParameters Eigenschaft fest. Die LayoutParams -Klasse ist die Android-Methode, um zu kapseln, wie Steuerelemente wiederverwendbar positioniert werden. Sobald eine instance eines Layouts erstellt wurde, können Steuerelemente erstellt und hinzugefügt werden. Steuerelemente verfügen LayoutParametersauch über , z TextView . B. in diesem Beispiel. Nachdem erstellt wurde, führt das TextView Hinzufügen zu und RelativeLayout das Festlegen von RelativeLayout als Inhaltsansicht dazu, dass die Anwendung wie gezeigt folgendes TextView anzeigt:

Schaltfläche

Erkennen der Ausrichtung im Code

Wenn eine Anwendung versucht, eine andere Benutzeroberfläche für jede Ausrichtung zu laden, wenn OnCreate aufgerufen wird (dies geschieht bei jeder Drehung eines Geräts), muss sie die Ausrichtung erkennen und dann den gewünschten Benutzeroberflächencode laden. Android verfügt über eine Klasse namens WindowManager, die verwendet werden kann, um die aktuelle Geräterotation über die WindowManager.DefaultDisplay.Rotation -Eigenschaft zu bestimmen, wie unten gezeigt:

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

Dieser Code legt fest, dass TextView 100 Pixel von der oberen linken Seite des Bildschirms positioniert werden soll, wobei automatisch das neue Layout animiert wird, wenn es ins Querformat gedreht wird, wie hier gezeigt:

Der Ansichtszustand wird im Hoch- und Querformat beibehalten.

Verhindern eines Aktivitätsneustarts

Zusätzlich zur Behandlung von alles in OnCreatekann eine Anwendung auch verhindern, dass eine Aktivität neu gestartet wird, wenn sich die Ausrichtung ändert, indem sie in ActivityAttribute wie folgt festlegenConfigurationChanges:

[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]

Wenn das Gerät nun rotiert wird, wird die Aktivität nicht neu gestartet. Um die Ausrichtungsänderung in diesem Fall manuell zu behandeln, kann eine Activity die OnConfigurationChanged -Methode überschreiben und die Ausrichtung des Configuration übergebenen Objekts bestimmen, wie in der neuen Implementierung der folgenden Aktivität:

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

Hier werden die TextView's Layoutparameter sowohl im Quer- als auch im Hochformat initialisiert. Klassenvariablen enthalten die Parameter zusammen mit dem TextView selbst, da die Aktivität nicht neu erstellt wird, wenn sich die Ausrichtung ändert. Der Code verwendet weiterhin den surfaceOrientartion in OnCreate , um das anfängliche Layout für festzulegen TextView. Danach OnConfigurationChanged werden alle nachfolgenden Layoutänderungen behandelt.

Wenn wir die Anwendung ausführen, lädt Android die Änderungen an der Benutzeroberfläche, wenn die Geräterotation auftritt, und startet die Aktivität nicht neu.

Verhindern eines Aktivitätsneustarts für deklarative Layouts

Aktivitätsneustarts, die durch die Geräterotation verursacht werden, können auch verhindert werden, wenn wir das Layout in XML definieren. Wir können diesen Ansatz beispielsweise verwenden, wenn wir einen Aktivitätsneustart (möglicherweise aus Leistungsgründen) verhindern möchten und keine neuen Ressourcen für verschiedene Ausrichtungen laden müssen.

Dazu befolgen wir dasselbe Verfahren, das wir mit einem programmgesteuerten Layout verwenden. Legen ConfigurationChanges Sie einfach in fest ActivityAttribute, wie in der CodeLayoutActivity vorherigen. Jeder Code, der für die Ausrichtungsänderung ausgeführt werden muss, kann erneut in der OnConfigurationChanged -Methode implementiert werden.

Beibehalten des Zustands bei Ausrichtungsänderungen

Unabhängig davon, ob die Rotation deklarativ oder programmgesteuert behandelt wird, sollten alle Android-Anwendungen dieselben Techniken für die Verwaltung des Zustands implementieren, wenn sich die Geräteausrichtung ändert. Die Verwaltung des Zustands ist wichtig, da das System eine ausgeführte Aktivität neu startet, wenn ein Android-Gerät rotiert wird. Android erleichtert das Laden alternativer Ressourcen, z. B. Layouts und Drawables, die speziell für eine bestimmte Ausrichtung entwickelt wurden. Wenn sie neu gestartet wird, verliert die Aktivität jeden vorübergehenden Zustand, den sie möglicherweise in lokalen Klassenvariablen gespeichert hat. Wenn also eine Aktivität zustandsabhängigkeit ist, muss sie ihren Zustand auf Anwendungsebene beibehalten. Eine Anwendung muss das Speichern und Wiederherstellen jedes Anwendungszustands verarbeiten, den sie über Ausrichtungsänderungen hinweg beibehalten möchte.

Weitere Informationen zum Beibehalten des Zustands in Android finden Sie im Leitfaden zum Aktivitätslebenszyklus .

Zusammenfassung

In diesem Artikel wurde beschrieben, wie Sie die integrierten Android-Funktionen zum Arbeiten mit Der Drehung verwenden. Zunächst wurde erläutert, wie Sie das Android-Ressourcensystem verwenden, um ausrichtungsfähige Anwendungen zu erstellen. Anschließend wurde gezeigt, wie Steuerelemente im Code hinzugefügt werden und wie Ausrichtungsänderungen manuell behandelt werden.