2016-08-18 40 views
5
Android Studio 2.1.3 

Mam ten projekt, który staram się naśladować.Otwórz drugą grę z szufladami jako grę z podziałem na szuflady nad pierwszym

Na pierwszym stole do gry mam opcje ustawień.

enter image description here

Kiedy użytkownik kliknie przycisk, otworzy drugi drawerlayout jak ten poniżej.

enter image description here

Użytkownik może wrócić do pierwszego, klikając na strzałkę Main Menu.

Czy to możliwe?

Wielkie dzięki za wszelkie sugestie

+0

Jest to możliwe, ale nie ze standardowym plikiem menu xml. Trzeba zrobić mały hack, dodając niestandardowy układ do 'NavigationView'. –

+0

Czy interesuje Cię tylko jak otworzyć drugą szufladę nad pierwszą? Chodzi mi o to, czy pytasz również, jak stylizować te poszczególne przedmioty, czy po prostu potrzebujesz funkcji podwójnej szuflady? –

+0

Chciałbym kliknąć ustawienia w pierwszym menu, a podmenu ustawień będzie animowane nad pierwszym. Zostało to zrobione z aplikacji Amazon, którą próbowałem skopiować w mojej własnej. – ant2009

Odpowiedz

5

Nie wiadomo, jak dokładnie chcesz realizować swoje szuflady UI, więc następujące rozwiązanie jest dość ogólny, w który powinien działać z NavigationView s, RecyclerView s, czyli prawie dowolnego typu z View s, które chcesz.

Rozwiązanie to wykorzystuje niestandardowy ViewSwitcher podklasę, która działa jak lewej szuflady DrawerLayout „s, i posiada dwie potomne View s, jeden jako główny szuflada View, a drugi jest druga szuflada, która otwiera się nad nim.

Klasa DoubleDrawerView jest stosunkowo proste ViewSwitcher który ładuje własne Animation s, a ongluje je odpowiednio dać efekt drugiego otworu i zamykania szuflady na pierwszej. Śledzi własnego stanu tak, że może on zostać przywrócone poprawnie po obróceniu urządzenia itp

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 wykorzystuje następujące pliki XML dla swoich Animation s. Powinny one znajdować się w folderze res/anim/ Twojego projektu.

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" /> 

układ tym przykładzie jest to standardowy DrawerLayout z DoubleDrawerView do szuflady, a dwa proste NavigationView s tam. Pamiętaj, że główna szuflada View musi być wymieniona najpierw wewnątrz DoubleDrawerView, z drugą, wewnętrzną szufladą View po.

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> 

Dla kompletnego wyciąć i wkleić przykład niektóre proste res/menu/ pliki dla NavigationView s powyżej.

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> 

W przykładzie Activity, my po prostu odnośniki do DoubleDrawerView i NavigationView s, i wdrożyć OnNavigationItemSelectedListener aby otworzyć i zamknąć szufladę wewnętrzną odpowiednio.

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

świetna odpowiedź Postaram się umieścić to do pracy – ant2009

4

Rozwiązanie to wykorzystuje dwie DrawerLayout, jedyna zagnieżdżone w drugim, zamiast niestandardowej View. To może być nieco łatwiejsze do wdrożenia, ale wymaga nieco bardziej wyspecjalizowany kod w samej Activity, a więc będzie bardziej ściśle sprzężone do niższej klasy jest używany w.

UKŁAD Activity „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" /> 

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

Przykład NavigationView s powyżej korzystać z tych samych plików menu jak pokazano na my other answer here.

W pliku Activity otrzymujemy odwołania do obu DrawerLayout s, a podczas uruchamiania uruchamiamy tryb koloru i blokady na wewnętrznym. Musimy również obsługiwać przycisk "Wstecz" naciskając na siebie, ponieważ dodanie drugiego DrawerLayout zakłóca działanie pierwszego z nich. Po otwarciu i zamknięciu wewnętrznej szuflady musimy odpowiednio ustawić tryb blokady, aby zapobiec przeciągnięciu wewnętrznej szuflady.

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

dzięki za odpowiedzi naprawdę coś się tutaj nauczyć. Poprawię to. – ant2009