2016-08-18 14 views
5
Android Studio 2.1.3 

Tôi có thiết kế này mà tôi đang cố gắng làm theo.Mở ngăn kéo thứ hai dưới dạng ngăn ngăn con phụ trên

Trên ngăn kéo đầu tiên, tôi có tùy chọn cài đặt.

enter image description here

Khi người dùng nhấp chuột, nó sẽ mở ra một DrawerLayout thứ hai như thế này dưới đây.

enter image description here

Người dùng có thể lấy lại cho người đầu tiên bằng cách nhấn vào mũi tên Main Menu.

Điều này có khả thi không?

Rất cám ơn cho bất cứ đề nghị

+0

Điều này có thể, nhưng không phải với tệp xml menu chuẩn. Bạn phải thực hiện một hack nhỏ bằng cách thêm bố cục tùy chỉnh vào 'NavigationView'. –

+0

Bạn có quan tâm đến cách mở ngăn kéo thứ hai trong lần đầu tiên không? Ý tôi là, bạn cũng hỏi cách tạo kiểu cho những vật phẩm cụ thể đó hay bạn chỉ muốn chức năng ngăn kéo đôi? –

+0

Tôi muốn nhấp vào cài đặt trong menu đầu tiên và menu phụ của cài đặt sẽ hoạt ảnh trên đầu tiên. Điều này được lấy từ ứng dụng amazon mà tôi đã cố gắng để lặp lại trong của riêng tôi. – ant2009

Trả lời

5

Đó là chưa rõ chính xác mà bạn muốn thực hiện giao diện người dùng ngăn kéo của bạn, vì vậy giải pháp sau đây là khá chung chung, ở chỗ nó sẽ làm việc với NavigationView s, RecyclerView s, hoặc khá nhiều bất cứ loại trong số View bạn muốn.

Giải pháp này sử dụng một tùy chỉnh ViewSwitcher lớp con có tác dụng như ngăn kéo bên trái một DrawerLayout 's, và giữ hai con View s, một là ngăn kéo chính View, và người kia là ngăn kéo thứ hai mở ra trên nó.

Lớp DoubleDrawerViewViewSwitcher tương đối đơn giản tải Animation s của riêng nó và tranh luận chúng một cách thích hợp để tạo hiệu ứng của ngăn mở thứ hai và đóng trên ngăn đầu tiên. Nó theo dõi trạng thái của nó để nó có thể được phục hồi một cách chính xác sau một vòng xoay thiết bị vv

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 sử dụng các tập tin XML sau cho Animation s của nó. Những thư mục này phải nằm trong thư mục res/anim/ của dự án của bạn.

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

bố trí của ví dụ này là một tiêu chuẩn DrawerLayout với một DoubleDrawerView cho ngăn kéo của mình, và hai đơn giản 0.123.s trong đó. Lưu ý rằng ngăn kéo chính View phải được liệt kê trước tiên bên trong DoubleDrawerView, với ngăn thứ hai, bên trong ngăn View sau.

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> 

Vì lợi ích của một vết cắt đầy đủ và dán dụ, một số res/menu/ file đơn giản cho NavigationView s trên.

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> 

Trong ví dụ Activity, chúng tôi chỉ nhận được tham chiếu đến DoubleDrawerViewNavigationView s, và thực hiện một OnNavigationItemSelectedListener để mở và đóng ngăn kéo bên trong cho phù hợp.

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

câu trả lời tuyệt vời Tôi sẽ cố gắng và đặt nó để làm việc – ant2009

4

Giải pháp này sử dụng hai DrawerLayout s, một lồng nhau trong khác, thay cho một phong tục View. Điều này có thể hơi dễ thực hiện hơn, nhưng nó yêu cầu mã chuyên biệt hơn một chút trong chính bản thân Activity và do đó sẽ được kết hợp chặt chẽ hơn với bất kỳ lớp nào được sử dụng.

Bố cục của 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> 

Ví dụ NavigationView s trên sử dụng các tập tin trình đơn tương tự như trong my other answer here.

Trong Activity, chúng tôi nhận được tham chiếu đến cả hai DrawerLayout s và đặt chế độ màu và khóa scrim ở chế độ bên trong khi khởi động. Chúng tôi cũng cần phải xử lý nút quay lại tự nhấn, vì việc thêm một giây DrawerLayout gây rối với lần xử lý đầu tiên của nó. Khi mở và đóng ngăn kéo bên trong, chúng ta cần đặt chế độ khóa phù hợp, để tránh kéo ngăn kéo bên trong.

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

cảm ơn cho câu trả lời thực sự là một cái gì đó để tìm hiểu ở đây. Tôi sẽ làm cho nó chính xác. – ant2009

Các vấn đề liên quan