2016-08-18 1 views
5
Android Studio 2.1.3 

J'ai ce design que j'essaie de suivre.Ouvrez la deuxième tirelire comme une sous-tiroirs sur la première

Sur la première boîte à tiroirs, j'ai une option d'arrangement.

enter image description here

Lorsque l'utilisateur clique, il ouvrira une deuxième drawerlayout comme celui-ci ci-dessous.

enter image description here

L'utilisateur peut revenir à la première en cliquant sur la flèche Main Menu.

Est-ce possible?

Un grand merci pour toutes les suggestions

+0

Ceci est possible, mais pas avec le fichier XML du menu standard. Vous devez faire un petit hack en ajoutant une mise en page personnalisée à 'NavigationView'. –

+0

Etes-vous juste intéressé par la façon d'ouvrir un deuxième tiroir sur le premier? Je veux dire, demandez-vous également comment styliser ces articles particuliers, ou vous voulez juste la fonctionnalité de double tiroir? –

+0

Je voudrais cliquer sur les paramètres dans le premier menu et le sous-menu des paramètres s'animera sur le premier. Cela a été pris de l'application Amazon que j'essayais de reproduire dans le mien. – ant2009

Répondre

5

On ne sait pas comment vous souhaitez exactement implémenter votre interface utilisateur de tiroir, de sorte que la solution suivante est assez générique, en ce sens qu'elle devrait travailler avec NavigationView s, RecyclerView s, ou à peu près tout type de View s vous souhaitez.

Cette solution utilise une mesure ViewSwitcher sous-classe qui agit comme un tiroir gauche de DrawerLayout, et détient deux enfants View s, l'une étant le principal tiroir View, et l'autre étant le deuxième tiroir qui ouvre sur elle.

La classe DoubleDrawerView est un ViewSwitcher relativement simple qui charge ses propres Animation s, et les jongle de façon appropriée pour donner l'effet d'une seconde ouverture du tiroir et la fermeture sur la première. Il suit son propre état afin qu'il puisse être restauré correctement après une rotation de l'appareil, etc.

public class DoubleDrawerView extends ViewSwitcher { 
    private static final int NONE = -1; 
    private static final int MAIN_VIEW_INDEX = 0; 
    private static final int DRAWER_VIEW_INDEX = 1; 

    private Animation slideInAnimation, slideOutAnimation, noAnimation; 
    private boolean animating = false; 

    private Animation.AnimationListener listener = new Animation.AnimationListener() { 
     @Override 
     public void onAnimationEnd(Animation anim) { 
      animating = false; 
     } 

     @Override 
     public void onAnimationStart(Animation anim) {} 

     @Override 
     public void onAnimationRepeat(Animation anim) {} 
    }; 

    public DoubleDrawerView(Context context) { 
     this(context, null); 
    } 

    public DoubleDrawerView(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     slideInAnimation = AnimationUtils.loadAnimation(context, R.anim.slide_in_left); 
     slideOutAnimation = AnimationUtils.loadAnimation(context, R.anim.slide_out_left); 
     noAnimation = AnimationUtils.loadAnimation(context, R.anim.none); 
     noAnimation.setAnimationListener(listener); 
    } 

    public void openInnerDrawer() { 
     if (getDisplayedChild() != DRAWER_VIEW_INDEX) { 
      setChildAndAnimate(DRAWER_VIEW_INDEX, true); 
     } 
    } 

    public void closeInnerDrawer() { 
     if (getDisplayedChild() != MAIN_VIEW_INDEX) { 
      setChildAndAnimate(MAIN_VIEW_INDEX, true); 
     } 
    } 

    public boolean isInnerDrawerOpen() { 
     return getDisplayedChild() == DRAWER_VIEW_INDEX; 
    } 

    private void setChildAndAnimate(int whichChild, boolean doAnimate) { 
     if (doAnimate) { 
      setAnimationForChild(whichChild); 
     } 
     else { 
      setAnimationForChild(NONE); 
     } 
     animating = doAnimate; 
     setDisplayedChild(whichChild); 
    } 

    private void setAnimationForChild(int whichChild) { 
     if (whichChild == DRAWER_VIEW_INDEX) { 
      setInAnimation(slideInAnimation); 
      setOutAnimation(noAnimation); 
     } 
     else if (whichChild == MAIN_VIEW_INDEX) { 
      setInAnimation(noAnimation); 
      setOutAnimation(slideOutAnimation); 
     } 
     else { 
      setInAnimation(null); 
      setOutAnimation(null); 
     } 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     if (animating) { 
      return true; 
     } 
     else { 
      return super.onInterceptTouchEvent(ev); 
     } 
    } 

    @Override 
    protected Parcelable onSaveInstanceState() { 
     Parcelable superState = super.onSaveInstanceState(); 
     SavedState ss = new SavedState(superState); 
     ss.whichChild = getDisplayedChild(); 
     return ss; 
    } 

    @Override 
    protected void onRestoreInstanceState(Parcelable state) { 
     SavedState ss = (SavedState) state; 
     super.onRestoreInstanceState(ss.getSuperState()); 
     setChildAndAnimate(ss.whichChild, false); 
    } 

    private static class SavedState extends BaseSavedState { 
     int whichChild; 

     SavedState(Parcelable superState) { 
      super(superState); 
     } 

     private SavedState(Parcel in) { 
      super(in); 
      whichChild = in.readInt(); 
     } 

     @Override 
     public void writeToParcel(Parcel out, int flags) { 
      super.writeToParcel(out, flags); 
      out.writeInt(whichChild); 
     } 

     public static final Parcelable.Creator<SavedState> 
      CREATOR = new Parcelable.Creator<SavedState>() { 

      public SavedState createFromParcel(Parcel in) { 
       return new SavedState(in); 
      } 

      public SavedState[] newArray(int size) { 
       return new SavedState[size]; 
      } 
     }; 
    } 
} 

DoubleDrawerView utilise les fichiers XML suivants pour ses Animation s. Ceux-ci doivent figurer dans le dossier res/anim/ de votre projet.

slide_in_left.xml

<translate xmlns:android="http://schemas.android.com/apk/res/android" 
    android:fromXDelta="-100%p" android:toXDelta="0" 
    android:duration="@android:integer/config_mediumAnimTime"/> 

slide_out_left.xml

<translate xmlns:android="http://schemas.android.com/apk/res/android" 
    android:fromXDelta="0" android:toXDelta="-100%p" 
    android:duration="@android:integer/config_mediumAnimTime"/> 

none.xml

<alpha xmlns:android="http://schemas.android.com/apk/res/android" 
    android:fromAlpha="1.0" android:toAlpha="1.0" 
    android:duration="@android:integer/config_mediumAnimTime" /> 

mise en page de cet exemple est un DrawerLayout standard avec un DoubleDrawerView pour son tiroir, et deux simples NavigationView s. Notez que le tiroir principal View doit être répertorié en premier dans le DoubleDrawerView, avec le deuxième tiroir intérieur View après.

activity_main.xml

<android.support.v4.widget.DrawerLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/drawer_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <FrameLayout 
     android:id="@+id/main_content" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" /> 

    <com.example.doubledrawer.DoubleDrawerView 
     android:id="@+id/double_drawer_view" 
     android:layout_width="240dp" 
     android:layout_height="match_parent" 
     android:layout_gravity="left"> 

     <android.support.design.widget.NavigationView 
      android:id="@+id/main_navigation_view" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      app:menu="@menu/navigation_main" /> 

     <android.support.design.widget.NavigationView 
      android:id="@+id/settings_navigation_view" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      app:menu="@menu/navigation_settings" /> 

    </com.example.doubledrawer.DoubleDrawerView> 

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

Par souci d'une coupe complète et coller par exemple, certains fichiers res/menu/ simples pour les NavigationView s ci-dessus.

navigation_main.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"> 

    <group 
     android:id="@+id/group_screens" 
     android:checkableBehavior="single"> 
     <item 
      android:id="@+id/menu_screen_1" 
      android:title="Screen 1" /> 
     <item 
      android:id="@+id/menu_screen_2" 
      android:title="Screen 2"/> 
    </group> 

    <item 
     android:id="@+id/menu_open_settings" 
     android:title="Open Settings" /> 

</menu> 

navigation_settings.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"> 

    <item 
     android:id="@+id/menu_close_settings" 
     android:title="Back to Main" /> 

    <group 
     android:id="@+id/group_settings"> 
     <item 
      android:id="@+id/menu_setting_1" 
      android:title="Setting 1" /> 
     <item 
      android:id="@+id/menu_setting_2" 
      android:title="Setting 2" /> 
    </group> 

</menu> 

Dans l'exemple Activity, nous obtenons simplement des références aux DoubleDrawerView et NavigationView s, et mettre en œuvre un OnNavigationItemSelectedListener pour ouvrir et fermer le tiroir intérieur en conséquence.

public class MainActivity extends AppCompatActivity 
    implements NavigationView.OnNavigationItemSelectedListener { 

    private DrawerLayout drawerLayout; 
    private DoubleDrawerView doubleDrawerView; 
    private NavigationView mainNavigationView, settingsNavigationView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); 
     doubleDrawerView = (DoubleDrawerView) findViewById(R.id.double_drawer_view); 
     mainNavigationView = (NavigationView) findViewById(R.id.main_navigation_view); 
     settingsNavigationView = (NavigationView) findViewById(R.id.settings_navigation_view); 

     mainNavigationView.setNavigationItemSelectedListener(this); 
     settingsNavigationView.setNavigationItemSelectedListener(this); 

     drawerLayout.openDrawer(Gravity.LEFT); 
    } 

    @Override 
    public boolean onNavigationItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      case R.id.menu_open_settings: 
       doubleDrawerView.openInnerDrawer(); 
       break; 

      case R.id.menu_close_settings: 
       doubleDrawerView.closeInnerDrawer(); 
       break; 

       // Additional cases as needed 
       // This example simply Toasts the title for the extra sample items 

      default: 
       Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT).show(); 
     } 
     return true; 
    } 
} 
+1

bonne réponse Je vais essayer de mettre cela au travail – ant2009

4

Cette solution utilise deux DrawerLayout s, une nichée dans l'autre, au lieu d'une coutume View. Cela pourrait être un peu plus facile à mettre en œuvre, mais il faut un peu plus de code spécialisé dans le Activity lui-même, et donc sera plus étroitement couplé à des classes selon qu'il est utilisé dans.

mise en page de la Activity, activity_main.xml.

<android.support.v4.widget.DrawerLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/drawer_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <FrameLayout 
     android:id="@+id/main_content" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" /> 

    <android.support.v4.widget.DrawerLayout 
     android:id="@+id/inner_drawer_layout" 
     android:layout_width="240dp" 
     android:layout_height="match_parent" 
     android:layout_gravity="left"> 

     <android.support.design.widget.NavigationView 
      android:id="@+id/main_navigation_view" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      app:menu="@menu/navigation_main" /> 

     <android.support.design.widget.NavigationView 
      android:id="@+id/settings_navigation_view" 
      android:layout_width="240dp" 
      android:layout_height="match_parent" 
      android:layout_gravity="left" 
      app:menu="@menu/navigation_settings" /> 

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

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

L'exemple ci-dessus NavigationView s utilisent les mêmes fichiers de menu, comme indiqué dans my other answer here.

Dans le Activity, nous obtenons des références aux deux DrawerLayout s, et définissons la couleur de canevas et le mode de verrouillage sur le mode interne au démarrage. Nous avons également besoin de manipuler le bouton arrière appuyez sur nous-mêmes, comme l'ajout d'un deuxième DrawerLayout dégâts avec la première manipulation de celui-ci. Lors de l'ouverture et de la fermeture du tiroir intérieur, nous devons régler le mode de verrouillage de manière appropriée, pour éviter de faire glisser le tiroir interne.

public class MainActivity extends AppCompatActivity 
    implements NavigationView.OnNavigationItemSelectedListener { 

    private DrawerLayout drawerLayout, innerDrawerLayout; 
    private NavigationView mainNavigationView, settingsNavigationView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); 
     innerDrawerLayout = (DrawerLayout) findViewById(R.id.inner_drawer_layout); 
     mainNavigationView = (NavigationView) findViewById(R.id.main_navigation_view); 
     settingsNavigationView = (NavigationView) findViewById(R.id.settings_navigation_view); 

     mainNavigationView.setNavigationItemSelectedListener(this); 
     settingsNavigationView.setNavigationItemSelectedListener(this); 

     innerDrawerLayout.setScrimColor(Color.TRANSPARENT); 
     innerDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); 

     drawerLayout.openDrawer(Gravity.LEFT); 
    } 

    @Override 
    public void onBackPressed() { 
     if (drawerLayout.isDrawerOpen(Gravity.LEFT)) { 
      drawerLayout.closeDrawer(Gravity.LEFT); 
     } 
     else { 
      super.onBackPressed(); 
     } 
    } 

    private void openInnerDrawer() { 
     innerDrawerLayout.openDrawer(Gravity.LEFT); 
     innerDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN); 
    } 

    private void closeInnerDrawer() { 
     innerDrawerLayout.closeDrawer(Gravity.LEFT); 
     innerDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); 
    } 

    @Override 
    public boolean onNavigationItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      case R.id.menu_open_settings: 
       openInnerDrawer(); 
       break; 

      case R.id.menu_close_settings: 
       closeInnerDrawer(); 
       break; 

      // Additional cases as needed 
      // This example simply Toasts the title for the extra sample items 

      default: 
       Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT).show(); 
     } 
     return true; 
    } 
} 
+1

merci pour les réponses vraiment quelque chose à apprendre ici. Je vais le faire correctement. – ant2009