2014-10-25 18 views
32

Nach the Material Design specs die Breite des Nav Schublade auf mobilen Geräten müssenMaterial Design: Nav Schublade Breite

sein

Seite nav width = Bildschirmbreite - ca. Barhöhe

Wie setzen wir diese auf Android ?

Ich habe zwei Teillösungen. Erstens ist die hacky Weise: in der Aktivität enthielten ich diesen Code setzen:

 
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR1) { 
    final Display display = getWindowManager().getDefaultDisplay(); 
    final Point size = new Point(); 
    display.getSize(size); 

    final ViewGroup.LayoutParams params = mDrawerFragment.getView().getLayoutParams(); 
    params.width = size.x - getResources().getDimensionPixelSize(
     R.dimen.abc_action_bar_default_height_material 
    ); 
    mFragmentUserList.getView().setLayoutParams(params); 
}

Dies verursacht jedoch einen zweiten Zyklus Layout und funktioniert nicht in Lebkuchen: es ist nicht optimal.

Die zweite Lösung beinhaltet das Hinzufügen eines Leerzeichens zwischen dem Fragment und dem drawerLayout. Es verschiebt jedoch den Schatten und die Stelle, an die der Benutzer drücken kann, um zur Haupt-App zurückzukehren. Es stürzt auch ab, wenn das "Hamburger" -Symbol gedrückt wird. Auch nicht optimal.

Gibt es eine bessere Lösung, vorzugsweise eine mit Stilen und XML?

Antwort

23

Mit dem Android Design Support Library ist es nun wirklich einfache Navigationsleiste einschließlich richtige Dimensionierung zu implementieren. Verwenden Sie die NavigationView und verwenden Sie entweder ihre Fähigkeit, Schublade aus Menü Ressource zu machen (Beispiel here) oder Sie können es einfach um die Ansicht, die Sie derzeit für die Anzeige Ihrer Liste (z. B. ListView, RecyclerView) verwenden. NavigationView kümmert sich dann um die Schubladengröße für Sie.

Hier ist ein Beispiel, wie ich die NavigationView um Listview gewickelt verwenden:

<?xml version="1.0" encoding="utf-8"?> 
<android.support.v4.widget.DrawerLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:id="@+id/navdrawer_layout" 
    android:fitsSystemWindows="true"> 

    <!-- Layout where content is shown --> 
    <RelativeLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

     <include android:id="@+id/toolbar" 
      layout="@layout/toolbar" /> 

     <FrameLayout 
      android:id="@+id/content_frame" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:layout_below="@id/toolbar" /> 

     <!-- Toolbar shadow for pre-lollipop --> 
     <View style="@style/ToolbarDropshadow" 
      android:layout_width="match_parent" 
      android:layout_height="3dp" 
      android:layout_below="@id/toolbar" /> 

    </RelativeLayout> 

    <android.support.design.widget.NavigationView 
     android:id="@+id/navigation_view" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:layout_gravity="start"> 

     <ListView 
      android:id="@+id/navdrawer_list" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:choiceMode="singleChoice" 
      android:dividerHeight="0dp" 
      android:divider="@null"/> 

    </android.support.design.widget.NavigationView> 

</android.support.v4.widget.DrawerLayout> 

Auf diese Weise können NavigationViews Dimensionierung und immer noch verwenden, um Ihre eigene Schublade Liste verwenden können. Obwohl es viel einfacher ist, die Schubladenliste aus der Menüressource zu entfernen (Beispiel here), können Sie keine benutzerdefinierten Ansichten für die Listenelemente verwenden.

+0

Dies funktioniert ziemlich gut für mich. Ich denke, das sollte die richtige Antwort sein, da es keinen Programmieraufwand vom Entwickler erfordert. Es ist jedoch in der Lage, die Richtlinien für die Breite der Navigationsleiste von Google vollständig zu erfüllen. –

+0

@logan: Sie haben Recht. Aber das war eine Frage, die älter als das materielle Alter ist ... – zubietaroberto

+0

@zubtaroberto Ja, natürlich weiß ich das. Aber es könnte immer noch jemanden geben, der Probleme mit dieser Art von Problemen hat und das könnte nützlich sein. – Logan

32

Ich schaffte es, eine Lösung mit XML-Stil Deklarationen zu machen, aber es ist ein bisschen hacky. Mein Ansatz bestand darin, Ränder zu verwenden, anstatt eine festgelegte Breite zu verwenden, um zu vermeiden, Code zur manuellen Berechnung des Layouts zu schreiben. Ich habe eine grundlegende Stilregel erstellt, um hervorzuheben, wie dies funktioniert.

Leider DrawerLayout verwendet derzeit eine minimale Marge von 64dp. Damit dieser Ansatz funktioniert, müssen wir diesen Wert mit negativen Rändern ausgleichen, damit wir die gewünschte Breite für die Navigationsleiste erhalten. Hoffentlich kann dies in Zukunft gelöst werden (Someone has filed an issue regarding it), so dass wir einfach auf die abc_action_bar_default_height_material Dimensionsreferenz für den Rand verweisen können.

folgenden Schritte aus:

  1. folgende Dimension und Formatdefinitionen hinzufügen:

    Werte/dimens.xml

    <!-- Match 56dp default ActionBar height on portrait orientation --> 
    <dimen name="nav_drawer_margin_offset">-8dp</dimen> 
    

    Werte Land/dimens. xml

    <!-- Match 48dp default ActionBar height on landscape orientation --> 
    <dimen name="nav_drawer_margin_offset">-16dp</dimen> 
    

    Werte/styles.xml

    <!-- Nav drawer style to set width specified by Material Design specification --> 
    <style name="NavDrawer"> 
        <item name="android:layout_width">match_parent</item> 
        <item name="android:layout_marginRight">@dimen/nav_drawer_margin_offset</item> 
    </style> 
    

    Werte-sw600dp/styles.xml

    <!-- Margin already matches ActionBar height on tablets, just modify width --> 
    <style name="NavDrawer"> 
        <item name="android:layout_width">320dp</item> 
        <item name="android:layout_marginRight">0dp</item> 
    </style> 
    
  2. Sobald Sie die obigen Regeln in Ihrem Projekt haben Sie hinzugefügt kann in Ihrer Navigationsleiste auf den NavDrawer Stil verweisen Ansicht:

    layout/navigation_drawer.xml (oder eine andere geeignete Ansicht für Ihre Navigationsleiste verwendet wird)

    <?xml version="1.0" encoding="utf-8"?> 
    <ListView xmlns:android="http://schemas.android.com/apk/res/android" 
        android:id="@+id/navigation_drawer" 
        style="@style/NavDrawer" 
        android:layout_height="match_parent" 
        android:layout_gravity="start" 
        android:choiceMode="singleChoice" 
        android:divider="@android:color/transparent" 
        android:dividerHeight="0dp" 
        android:background="#FFF" 
    /> 
    
+2

Sollte angenommen werden, wie beantwortet, diese Info ist genial. Danke, Mann. – MiguelCatalan

8

Nach einer einfacheren Lösung suchen, fand ich einen sehr Klärung Artikel: Material Navigation Drawer sizing.

Hier:

Der Nexus 5-Bildschirm ist eine nette 640 x 360 dp (xxhdpi) und eine app bar auf ist es dp 56 hoch. So sollte die nav Schublade sein:

[Breite in dp] = 360dp - 56dp = 304dp

A Nexus 4 Sport ein 640 x 384 dp (xhdpi) Bildschirm statt. Gleiche 56-dpi-App-Balkenhöhe. Seine Navigationsschublade?

[Breite in dp] = 384dp - 56dp = 328dp

Also, wie die Google-Designer kommen mit 288dp und 304dp Breiten bzw.? Ich habe keine Ahnung.

Google-Apps, auf auf der anderen Seite, scheinen mit meiner Mathematik zu stimmen. Oh, und Sie wissen, was das lustigste Ding in all dem ist? Das iPhone (das einen anderen Bildschirm hat Höhen, aber eine konstante 320 dp Breite) ist korrekt als eine 264dp Nav Schublade gekennzeichnet.

Grundsätzlich zeigt sich, dass einige Richtlinien über die Navigationsleiste selbst widersprechen und dass Sie die folgende Regel Berechnungen verwenden können, um zu vermeiden:

Sie können grundsätzlich immer 304dp auf -sw360dp und 320dp auf -sw384dp verwenden für Ihre Navigationsschublade, und Sie werden es richtig machen.

4

Sie bereits aktualisiert specs, jetzt Breite Navigationsleiste ist:

Math.min(screenWidth — actionBarSize, 6 * actionBarSize); 
+1

"Die Breite des Seitennavs entspricht der Breite des Bildschirms abzüglich der Höhe der Aktionsleiste, in diesem Fall 56dp vom rechten Bildschirmrand. Die maximale Breite der Navigationsleiste beträgt das 5-fache des Standardinkrements (56dp auf Mobilgeräten und 64dp auf Tablets). " Woher bekommen Sie 6 * actionbarSize? – DDukesterman

+0

Ja, es ist 5, aber 5 sieht einfach nicht richtig aus, während 6, sieht aus wie es ist ein Tipp in der Dokumentation. Ich war auf der Suche nach einer Möglichkeit, dies einzureichen, kann aber keine finden. – vovkab

+0

Btw, wenn Sie ihren Screenshot überprüfen und es messen werden Sie feststellen, dass es definitiv nicht 5 ist :) http://www.google.com/design/spec/patterns/navigation-drawer.html – vovkab

0

Nun, ich fand dies sehr schwierig zu verstehen und umzusetzen. Unglücklicherweise machte Matthews Lösung meine Nav-Schublade zu breit für die Landschaft, und es schien gegen Google's Praktiken zu verstoßen, d. H. Die Navigationsbreite wird durch die kleinste Breite des Geräts bestimmt. Auf jeden Fall würde es in meinem Fall nicht funktionieren, da ich die Konfiguration in meinem Manifest deaktiviert habe. Also habe ich beschlossen, die Nav-Breite dynamisch mit dem folgenden Code zu ändern.

Es sollte angemerkt werden meine App ist nur für Telefone und ich entschied mich für 320dp ist die maximale Breite. Dies ist auch der Grund, warum ich für beide Ausrichtungen eine Werkzeughöhe von 56dp festgelegt habe.

Ich hoffe, es hilft jemandem, und dass sie den unnötigen Stress vermeiden können, den es verursacht hat.

navDrawLayout.post(new Runnable() 
    { 

     @Override 
     public void run() { 

      Resources r = getResources(); 

      DisplayMetrics metrics = new DisplayMetrics(); 

      if(r.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){ 

       getWindowManager().getDefaultDisplay().getMetrics(metrics); 
       int height = metrics.heightPixels; 

       float screenWidth = height/r.getDisplayMetrics().density; 
       float navWidth = (screenWidth - 56); 

       navWidth = Math.min(navWidth, 320); 

       int newWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, navWidth, r.getDisplayMetrics()); 

       DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) navDrawLayout.getLayoutParams(); 
       params.width = newWidth; 
       navDrawLayout.setLayoutParams(params);  


      } 

      if(r.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { 

      getWindowManager().getDefaultDisplay().getMetrics(metrics); 
      int width = metrics.widthPixels; 

      float screenWidth = width/r.getDisplayMetrics().density; 
      float navWidth = screenWidth - 56; 

      navWidth = Math.min(navWidth, 320); 

      int newWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, navWidth, r.getDisplayMetrics()); 

      DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) navDrawLayout.getLayoutParams(); 
      params.width = newWidth; 
      navDrawLayout.setLayoutParams(params); 


      } 
     } 

    } 
    ); 
Verwandte Themen