Share via


Verarbeiten der Drehung

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

Übersicht

Da mobile Geräte leicht gedreht werden, ist integrierte Drehung ein Standardfeature in mobilen OSes. Android bietet ein komplexes Framework für den Umgang mit Drehungen innerhalb von Anwendungen, unabhängig davon, ob die Benutzeroberfläche deklarativ in XML oder programmgesteuert im Code erstellt wird. Bei der automatischen Behandlung von deklarativen Layoutänderungen auf einem gedrehten Gerät kann eine Anwendung von der engen Integration mit dem Android-Ressourcensystem profitieren. Bei programmgesteuertem Layout müssen Änderungen manuell behandelt werden. Dies ermöglicht eine feinere Kontrolle zur Laufzeit, aber auf Kosten von mehr Arbeit für den Entwickler. Eine Anwendung kann sich auch entscheiden, den Neustart der Aktivität zu deaktivieren und manuelle Kontrolle über Ausrichtungsänderungen zu übernehmen.

In diesem Leitfaden werden die folgenden Ausrichtungsthemen untersucht:

  • Deklarative Layoutdrehung – Verwenden des Android-Ressourcensystems zum Erstellen von ausrichtungsfähigen Anwendungen, einschließlich des Ladens von Layouts und Drawables für bestimmte Ausrichtungen.

  • Programmgesteuerte Layoutdrehung – Programmgesteuertes Hinzufügen von Steuerelementen sowie manuelle Behandlung von Ausrichtungsänderungen.

Deklaratives Behandeln der Drehung mit Layouts

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

  • Layoutressourcen – Angeben, welche Layoutdateien für jede Ausrichtung aufgeblasen werden.

  • Drawable Resources – Angeben, welche Drawables für jede Ausrichtung geladen werden.

Layoutressourcen

Standardmäßig werden im Ordner "Ressourcen/Layout" enthaltene Android-XML-Dateien (Android XML) zum Rendern von Ansichten für eine Aktivität verwendet. Die Ressourcen dieses Ordners werden sowohl für Hoch- als auch für 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 "Ressourcen/Layout" . Wenn die Methode "Activity OnCreate " aufgerufen wird, wird die in "Main.axml" definierte Ansicht aufgeblasen, die eine Schaltfläche deklariert, wie im XML-Code unten dargestellt:

<?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 in die Querformatausrichtung gedreht wird, wird die Methode der Aktivität OnCreate erneut aufgerufen, und dieselbe Main.axml-Datei wird aufgeblasen, wie im folgenden Screenshot gezeigt:

Gleicher Bildschirm, im Querformat

Ausrichtungsspezifische Layouts

Neben dem Layoutordner (standardmäßig im Hochformat und auch explizit benannter Layoutport durch Einschließen eines Ordners mit dem Namen layout-land), kann eine Anwendung die benötigten Ansichten definieren, wenn im Querformat keine Codeänderungen vorgenommen werden.

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 Datei "Main.axml " enthält, führt das Aufblasen des Layouts im Querformat nun dazu, dass Android das neu hinzugefügte "Main.axml" lädt. Betrachten Sie die Querformatversion der Datei "Main.axml ", die den folgenden Code enthält (aus Gründen der Einfachheit ähnelt diese XML der Standardformatversion des Codes, verwendet jedoch eine andere Zeichenfolge in der 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 drehen, wird das neue XML-Laden veranschaulicht, wie unten dargestellt:

Screenshots für Hoch- und Querformat, die den Hochformatmodus drucken

Drawable Resources

Während der Drehung behandelt Android drawable-Ressourcen ähnlich wie Layoutressourcen. In diesem Fall erhält das System die Drawables aus den Ordnern "Resources/drawable " bzw . "Resources/drawable-land ".

Angenommen, das Projekt enthält ein Bild mit dem Namen Monkey.png im Ordner "Ressourcen/Drawable ", auf das aus einem ImageView XML-Code 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" />

Gehen wir weiter davon aus, dass eine andere Version von Monkey.png unter Ressourcen/Drawable-Land enthalten ist. Genau wie bei den Layoutdateien ändert sich, wenn das Gerät gedreht wird, die zeichnungsfähigen Änderungen für die angegebene Ausrichtung, wie unten dargestellt:

Unterschiedliche Version von Monkey.png im Hoch- und Querformat angezeigt

Programmgesteuertes Behandeln der Drehung

Manchmal definieren wir Layouts im Code. Dies kann aus verschiedenen Gründen geschehen, einschließlich technischer Einschränkungen, Entwicklerpräferenz usw. Wenn wir Steuerelemente programmgesteuert hinzufügen, muss eine Anwendung manuell die Geräteausrichtung berücksichtigen, die 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 z. B. eine Benutzeroberfläche, die aus einem einzelnen TextView Steuerelement besteht, das einem Steuerelement hinzugefügt wurde RelativeLayout, wie im folgenden Code dargestellt.

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 Instanz einer RelativeLayout Klasse und legt seine LayoutParameters Eigenschaft fest. Die Klasse ist die LayoutParams Art und Weise von Android, wie Steuerelemente wiederverwendbar positioniert werden. Sobald eine Instanz eines Layouts erstellt wurde, können Steuerelemente erstellt und hinzugefügt werden. Steuerelemente verfügen LayoutParametersauch über , z. B. das TextView in diesem Beispiel. Nachdem die TextView App erstellt wurde, fügen Sie sie hinzu RelativeLayout und legen sie RelativeLayout so fest, dass die Inhaltsansicht dazu führt, dass die Anwendung die TextView folgende Abbildung anzeigt:

Inkrement-Zählerschaltfläche, die im Hoch- und Querformat angezeigt wird

Erkennen der Ausrichtung im Code

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

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

Mit diesem Code wird festgelegt, dass er TextView 100 Pixel von oben links auf dem Bildschirm positioniert wird, wobei das neue Layout automatisch animiert wird, wenn er in das Querformat gedreht wird, wie hier gezeigt:

Der Ansichtszustand wird im Hoch- und Querformat beibehalten.

Verhindern des Neustarts von Aktivitäten

Neben der Behandlung aller Elemente OnCreatekann eine Anwendung auch verhindern, dass eine Aktivität neu gestartet wird, wenn sich die Ausrichtung ändert, indem Sie folgendes ActivityAttribute festlegenConfigurationChanges:

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

Wenn das Gerät gedreht wird, wird die Aktivität nicht neu gestartet. Um die Ausrichtungsänderung in diesem Fall manuell zu behandeln, kann eine Aktivität die OnConfigurationChanged Methode überschreiben und die Ausrichtung des Configuration objekts bestimmen, das übergeben wird, 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 Querformat als auch im Hochformat initialisiert. Klassenvariablen enthalten die Parameter zusammen mit dem TextView selbst, da die Aktivität beim Ändern der Ausrichtung nicht neu erstellt wird. Der Code verwendet weiterhin das surfaceOrientartion In OnCreate , um das anfängliche Layout für die TextView. OnConfigurationChanged Anschließend werden alle nachfolgenden Layoutänderungen behandelt.

Wenn wir die Anwendung ausführen, lädt Android die Benutzeroberfläche, während die Gerätedrehung auftritt, und startet die Aktivität nicht neu.

Verhindern des Neustarts von Aktivitäten für deklarative Layouts

Aktivitätsneustarts, die durch die Gerätedrehung verursacht werden, können auch verhindert werden, wenn das Layout in XML definiert wird. Beispielsweise können wir diesen Ansatz verwenden, wenn wir einen Aktivitätsneustart (aus Leistungsgründen, vielleicht) verhindern möchten, und wir müssen keine neuen Ressourcen für unterschiedliche Ausrichtungen laden.

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

Beibehalten des Zustands während Der Ausrichtungsänderungen

Unabhängig davon, ob die Drehung deklarativ oder programmgesteuert behandelt wird, sollten alle Android-Anwendungen dieselben Techniken zum Verwalten 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 gedreht 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 einen vorübergehenden Zustand, den sie möglicherweise in lokalen Klassenvariablen gespeichert hat. Daher muss eine Aktivität, wenn ein Status abhängig ist, seinen Zustand auf Anwendungsebene beibehalten. Eine Anwendung muss das Speichern und Wiederherstellen eines Anwendungszustands behandeln, den sie über Ausrichtungsänderungen hinweg beibehalten möchte.

Weitere Informationen zum Beibehalten des Zustands in Android finden Sie im Activity Lifecycle-Handbuch .

Zusammenfassung

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