Konfigurationsänderungen verarbeiten

Responsive Benutzeroberfläche und Navigation

Um Ihren Nutzern die bestmögliche Navigation zu bieten, sollten Sie eine Navigations-UI bereitstellen, die auf die Breite, Höhe und die kleinste Breite des Geräts ist. Sie können auch ein untere App-Leiste immer vorhanden oder minimierbar Navigationsleiste, ein Bahn oder vielleicht auch etwas völlig Neues, das auf dem verfügbaren Bildschirm den einzigartigen Stil der App.

<ph type="x-smartling-placeholder">
</ph> Beispiele für eine Schiene, Navigationsleisten und eine untere App-Leiste
Abbildung 1: Beispiele für eine Schiene, Navigationsleisten und App-Leiste unten

Das Material Design Leitfaden zur Produktarchitektur bietet zusätzlichen Kontext und Überlegungen zum Erstellen einer responsiven UI, die eine Benutzeroberfläche, die sich dynamisch an Umgebungsänderungen anpasst. Einige Beispiele für Dazu gehören Anpassungen von Breite, Höhe, Ausrichtung und Spracheinstellung des Nutzers. Diese Umwelteigenschaften sind kollektiv Dies wird als Konfiguration des Geräts bezeichnet.

Wenn sich mindestens eines dieser Eigenschaften während der Laufzeit ändert, reagiert das Android-Betriebssystem von Zerstören und anschließendes Neuerstellen der Aktivitäten und Fragmente Ihrer App. Daher sollten Sie zur Unterstützung einer responsiven UI unter Android dass Sie das richtige Qualifier für Ressourcenkonfiguration und gegebenenfalls vermeiden der Verwendung hartcodierter Layoutgrößen.

Globale Navigation in einer responsiven UI implementieren

Die Implementierung der globalen Navigation als Teil einer responsiven UI beginnt mit dem Aktivität, in der Ihr Navigationsdiagramm gehostet wird. Ein praktisches Beispiel finden Sie die Codelab zur Navigation. Im Codelab wird ein NavigationView- um das Navigationsmenü anzuzeigen (siehe Abbildung 2). Bei Ausführung auf einem Gerät das bei einer Breite von mindestens 960 dp gerendert wird, ist dieses NavigationView immer zu präsentieren.

<ph type="x-smartling-placeholder">
</ph> Das Navigations-Codelab verwendet
eine Navigationsansicht, die immer sichtbar ist,
            bei einer Gerätebreite von mindestens 960 dp
Abbildung 2: Im Codelab „Navigation“ werden NavigationView, um das Navigationsmenü aufzurufen.

Andere Gerätegrößen und -ausrichtungen wechseln dynamisch zwischen DrawerLayout oder BottomNavigationView nach Bedarf anpassen.

<ph type="x-smartling-placeholder">
</ph> eine Unternavigationsansicht und ein Schubladenlayout, das für die Navigation
            bei Bedarf in kleineren Gerätelayouts
Abbildung 3: Im Codelab „Navigation“ werden BottomNavigationView und DrawerLayout zum Anzeigen auf kleineren Geräten über das Navigationsmenü.

Sie können dieses Verhalten implementieren, indem Sie drei verschiedene Layouts erstellen, in denen jedes Layout definiert die gewünschten Navigationselemente und die Ansichtshierarchie basierend auf dem aktuelle Gerätekonfiguration

Die Konfiguration, für die die einzelnen Layouts gelten, wird durch das Verzeichnis Struktur, in der die Layoutdatei platziert wird. Beispiel: NavigationView Die Layoutdatei befindet sich im Verzeichnis res/layout-w960dp.

<!-- res/layout-w960dp/navigation_activity.xml -->
<RelativeLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context="com.example.android.codelabs.navigation.MainActivity">

   <com.google.android.material.navigation.NavigationView
       android:id="@+id/nav_view"
       android:layout_width="wrap_content"
       android:layout_height="match_parent"
       android:layout_alignParentStart="true"
       app:elevation="0dp"
       app:headerLayout="@layout/nav_view_header"
       app:menu="@menu/nav_drawer_menu" />

   <View
       android:layout_width="1dp"
       android:layout_height="match_parent"
       android:layout_toEndOf="@id/nav_view"
       android:background="?android:attr/listDivider" />

   <androidx.appcompat.widget.Toolbar
       android:id="@+id/toolbar"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentTop="true"
       android:layout_toEndOf="@id/nav_view"
       android:background="@color/colorPrimary"
       android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />

   <androidx.fragment.app.FragmentContainerView
       android:id="@+id/my_nav_host_fragment"
       android:name="androidx.navigation.fragment.NavHostFragment"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_below="@id/toolbar"
       android:layout_toEndOf="@id/nav_view"
       app:defaultNavHost="true"
       app:navGraph="@navigation/mobile_navigation" />
</RelativeLayout>

Die untere Navigationsansicht befindet sich im Verzeichnis res/layout-h470dp:

<!-- res/layout-h470dp/navigation_activity.xml -->
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical"
   tools:context="com.example.android.codelabs.navigation.MainActivity">

   <androidx.appcompat.widget.Toolbar
       android:id="@+id/toolbar"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:background="@color/colorPrimary"
       android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />

   <androidx.fragment.app.FragmentContainerView
       android:id="@+id/my_nav_host_fragment"
       android:name="androidx.navigation.fragment.NavHostFragment"
       android:layout_width="match_parent"
       android:layout_height="0dp"
       android:layout_weight="1"
       app:defaultNavHost="true"
       app:navGraph="@navigation/mobile_navigation" />

   <com.google.android.material.bottomnavigation.BottomNavigationView
       android:id="@+id/bottom_nav_view"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       app:menu="@menu/bottom_nav_menu" />
</LinearLayout>

Das Leistenlayout befindet sich im Verzeichnis res/layout. Dieses Verzeichnis verwenden für Standardlayouts ohne konfigurationsspezifische Qualifier:

<!-- res/layout/navigation_activity.xml -->
<androidx.drawerlayout.widget.DrawerLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/drawer_layout"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context="com.example.android.codelabs.navigation.MainActivity">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/toolbar"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:background="@color/colorPrimary"
           android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />

       <androidx.fragment.app.FragmentContainerView
           android:id="@+id/my_nav_host_fragment"
           android:name="androidx.navigation.fragment.NavHostFragment"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           app:defaultNavHost="true"
           app:navGraph="@navigation/mobile_navigation" />
   </LinearLayout>

   <com.google.android.material.navigation.NavigationView
       android:id="@+id/nav_view"
       android:layout_width="wrap_content"
       android:layout_height="match_parent"
       android:layout_gravity="start"
       app:menu="@menu/nav_drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>

Android folgt einer Prioritätsreihenfolge bei der Entscheidung, welche Ressourcen angewandt werden sollen. Spezifisch in diesem Beispiel: -w960dp (oder die verfügbare Breite ≥ 960 dp) hat Vorrang vor -h470dp (oder den verfügbaren Höhe >= 470). Wenn die Gerätekonfiguration mit keiner dieser Einstellungen übereinstimmt dann wird die Standard-Layoutressource (res/layout/navigation_activity.xml) wird verwendet.

Für die Verarbeitung von Navigationsereignissen müssen Sie nur die Ereignisse verknüpfen, die zu den derzeit vorhandenen Widgets hinzu, wie im folgenden Beispiel gezeigt.

Kotlin

class MainActivity : AppCompatActivity() {

   private lateinit var appBarConfiguration : AppBarConfiguration

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.navigation_activity)
      val drawerLayout : DrawerLayout? = findViewById(R.id.drawer_layout)
      appBarConfiguration = AppBarConfiguration(
                  setOf(R.id.home_dest, R.id.deeplink_dest),
                  drawerLayout)

      ...

      // Initialize the app bar with the navigation drawer if present.
      // If the drawerLayout is not null here, a Navigation button will be added
      // to the app bar whenever the user is on a top-level destination.
      setupActionBarWithNavController(navController, appBarConfig)

      // Initialize the NavigationView if it is present,
      // so that clicking an item takes
      // the user to the appropriate destination.
      val sideNavView = findViewById<NavigationView>(R.id.nav_view)
      sideNavView?.setupWithNavController(navController)

      // Initialize the BottomNavigationView if it is present,
      // so that clicking an item takes
      // the user to the appropriate destination.
      val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav_view)
      bottomNav?.setupWithNavController(navController)

      ...
    }

    ...
}

Java

public class MainActivity extends AppCompatActivity {

   private AppBarConfiguration appBarConfiguration;

   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.navigation_activity);
       NavHostFragment host = (NavHostFragment) getSupportFragmentManager()
               .findFragmentById(R.id.my_nav_host_fragment);
       NavController navController = host.getNavController();

       DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
       appBarConfiguration = new AppBarConfiguration.Builder(
               R.id.home_dest, R.id.deeplink_dest)
               .setDrawerLayout(drawerLayout)
               .build();

       // Initialize the app bar with the navigation drawer if present.
       // If the drawerLayout is not null here, a Navigation button will be added to
       // the app bar whenever the user is on a top-level destination.
       NavigationUI.setupActionBarWithNavController(
               this, navController, appBarConfiguration);


       // Initialize the NavigationView if it is present,
       // so that clicking an item takes
       // the user to the appropriate destination.
       NavigationView sideNavView = findViewById(R.id.nav_view);
       if(sideNavView != null) {
           NavigationUI.setupWithNavController(sideNavView, navController);
       }

       // Initialize the BottomNavigationView if it is present,
       // so that clicking an item takes
       // the user to the appropriate destination.
       BottomNavigationView bottomNav = findViewById(R.id.bottom_nav_view);
       if(bottomNav != null) {
           NavigationUI.setupWithNavController(bottomNav, navController);
       }

   }
}

Wenn sich die Gerätekonfiguration ändert, es sei denn, nicht anders konfiguriert, Android löscht die Aktivität aus der vorherigen Konfiguration sowie zugehörigen Datenansichten. Anschließend wird die Aktivität mit Ressourcen nachgestellt, die für die neue Konfiguration. Wenn die Aktivität zerstört und neu erstellt wird, wird automatisch die richtigen globalen Navigationselemente in onCreate() verbunden.

Alternativen zur geteilten Ansicht erwägen

Split View-Layouts oder Master-/Detail-Layouts wurden eine sehr beliebte und empfohlene Methode zur Entwicklung von Designs für Tablets und andere große Bildschirme. Geräte.

Seit der Einführung von Android-Tablets ist das Angebot an Geräten gewachsen. schnell ändern. Ein Faktor, der den Designraum für große wurde der Mehrfenstermodus eingeführt, Freiform-Fenster, deren Größe vollständig angepasst werden kann, wie z. B. auf ChromeOS-Geräten. Dadurch wird jeder Bildschirm Ihrer App responsiv, anstatt die Navigationsstruktur je nach Bildschirm Größe.

Es ist zwar möglich, eine Layout-Oberfläche für eine geteilte Ansicht mithilfe von Navigationsbibliothek verwenden, sollten Sie andere Alternativen in Betracht ziehen.

Zielnamen

Wenn Sie Zielnamen in der Grafik mithilfe der android:label verwenden Sie immer Ressourcenwerte, damit Ihre Inhalte lokalisiert werden.

<navigation ...>
    <fragment
        android:id="@+id/my_dest"
        android:name="com.example.MyFragment"
        android:label="@string/my_dest_label"
        tools:layout="@layout/my_fragment" />
    ...

Mit Ressourcenwerten haben Ihre Ziele automatisch die am besten geeigneten die angewendet werden, wenn sich Ihre Konfiguration ändert.