Làm cách nào để thêm một dấu phân cách phần cho Ngăn điều hướng trong Android?


90

Tôi có một ngăn điều hướng như hình ảnh này. Tôi muốn thêm một dấu phân cách phần (như đường phân cách Sao Hải Vương). Nó có vẻ đơn giản nhưng tôi không thể tìm thấy bất kỳ điều gì trên web hữu ích cho trường hợp của tôi.

Đây là MainActivity của tôi:

public class MainActivity extends Activity {
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;

    private CharSequence mDrawerTitle;
    private CharSequence mTitle;
    private String[] mPlanetTitles;

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

        mTitle = mDrawerTitle = getTitle();
        mPlanetTitles = getResources().getStringArray(R.array.planets_array);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        // set a custom shadow that overlays the main content when the drawer opens
        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
        // set up the drawer's list view with items and click listener
        mDrawerList.setAdapter(new ArrayAdapter<String>(this,
                R.layout.drawer_list_item, mPlanetTitles));
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

        // enable ActionBar app icon to behave as action to toggle nav drawer
        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        // ActionBarDrawerToggle ties together the the proper interactions
        // between the sliding drawer and the action bar app icon
        mDrawerToggle = new ActionBarDrawerToggle(
                this,                  /* host Activity */
                mDrawerLayout,         /* DrawerLayout object */
                R.drawable.ic_drawer,  /* nav drawer image to replace 'Up' caret */
                R.string.drawer_open,  /* "open drawer" description for accessibility */
                R.string.drawer_close  /* "close drawer" description for accessibility */
                ) {
            public void onDrawerClosed(View view) {
                getActionBar().setTitle(mTitle);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            }

            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(mDrawerTitle);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        if (savedInstanceState == null) {
            selectItem(0);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    /* Called whenever we call invalidateOptionsMenu() */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content view
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
         // The action bar home/up action should open or close the drawer.
         // ActionBarDrawerToggle will take care of this.
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        // Handle action buttons
        switch(item.getItemId()) {
        case R.id.action_websearch:
            // create intent to perform web search for this planet
            Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
            intent.putExtra(SearchManager.QUERY, getActionBar().getTitle());
            // catch event that there's no activity to handle intent
            if (intent.resolveActivity(getPackageManager()) != null) {
                startActivity(intent);
            } else {
                Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show();
            }
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    /* The click listner for ListView in the navigation drawer */
    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            selectItem(position);
        }
    }

    private void selectItem(int position) {
        // update the main content by replacing fragments
        Fragment fragment = new PlanetFragment();
        Bundle args = new Bundle();
        args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
        fragment.setArguments(args);

        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();

        // update selected item and title, then close the drawer
        mDrawerList.setItemChecked(position, true);
        setTitle(mPlanetTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
    }

    @Override
    public void setTitle(CharSequence title) {
        mTitle = title;
        getActionBar().setTitle(mTitle);
    }

    /**
     * When using the ActionBarDrawerToggle, you must call it during
     * onPostCreate() and onConfigurationChanged()...
     */

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // Pass any configuration change to the drawer toggls
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    /**
     * Fragment that appears in the "content_frame", shows a planet
     */
    public static class PlanetFragment extends Fragment {
        public static final String ARG_PLANET_NUMBER = "planet_number";

        public PlanetFragment() {
            // Empty constructor required for fragment subclasses
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_planet, container, false);
            int i = getArguments().getInt(ARG_PLANET_NUMBER);
            String planet = getResources().getStringArray(R.array.planets_array)[i];

            int imageId = getResources().getIdentifier(planet.toLowerCase(Locale.getDefault()),
                            "drawable", getActivity().getPackageName());
            ((ImageView) rootView.findViewById(R.id.image)).setImageResource(imageId);
            getActivity().setTitle(planet);
            return rootView;
        }
    }
}

activity_main.xml:

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

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

    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#111"/>
</android.support.v4.widget.DrawerLayout>

draw_list_item.xml:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceListItemSmall"
    android:gravity="center_vertical"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:textColor="#fff"
    android:background="?android:attr/activatedBackgroundIndicator"
    android:minHeight="?android:attr/listPreferredItemHeightSmall"/>

Tôi muốn điều này trở nên đơn giản nhưng tôi không thể tìm thấy bất cứ điều gì tốt trên web. Có cách nào để tôi có thể tách Neptune và tạo một phần cho nó không? Có ai có bất kỳ đề nghị? Cảm ơn.

nhập mô tả hình ảnh ở đây


bạn sẽ không thể làm điều đó như vậy với một adatper tiêu chuẩn. bạn sẽ cần tạo một bộ điều hợp tùy chỉnh và có một số đăng nhập đơn giản trên getView để ẩn hoặc hiển thị trình phân tách
Tomer Shemesh

@TomerShemesh Bạn có ví dụ về cách tôi có thể làm điều này không?
Redson

có những thư viện trên github sẽ giúp bạn đạt được điều tương tự. MaterialDrawer của mikepenz là một cái tốt và được bảo trì tốt. github.com/mikepenz/MaterialDrawer . Bạn cũng có thể theo dõi ứng dụng lịch trình google io trên github. Dấu phân cách chỉ là một chế độ xem có chiều cao 1px và chiều rộng match_parent
Raghunandan

@Raghunandan Tôi biết rằng dấu phân cách là một Viewnhưng tôi cần phải tìm cách nào đó để chỉ gọi nó cho sao Hải Vương
Redson

@Alias ​​theo dõi ứng dụng lịch trình google io hoặc sử dụng thư viện mà tôi vừa đăng liên kết. Cả hai đều nên hoạt động
Raghunandan

Câu trả lời:


325

Đảm bảo rằng bạn xác định mỗi nhóm bằng một ID duy nhất , dấu phân tách sẽ không xuất hiện nếu không có ID.

Ví dụ, đây là của tôi drawer_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group
        android:id="@+id/menu_top"
        android:checkableBehavior="single">
        <item
            android:checked="true"
            android:id="@+id/drawer_item_timeline"
            android:icon="@drawable/ic_timer_grey600_24dp"
            android:title="@string/drawer_timeline"/>
        <item
            android:id="@+id/drawer_item_reports"
            android:icon="@drawable/ic_timetable_grey600_24dp"
            android:title="@string/drawer_reports"/>
    </group>

    <group
        android:id="@+id/menu_bottom"
        android:checkableBehavior="none">

        <item
            android:id="@+id/drawer_item_settings"
            android:icon="@drawable/ic_settings_black_24dp"
            android:title="@string/drawer_settings" >
        </item>
    </group>
</menu>

Ngăn kéo mẫu

Gabriel cho biết thêm bên dưới trong phần nhận xét rằng nếu nhóm không có id, dấu phân tách sẽ không xuất hiện.


142
Điều quan trọng cần nói là nếu nhóm không có id, dấu phân tách sẽ không xuất hiện!
Gabriel Gómez

1
Có vẻ thực sự tốt cho đến nay, nhưng làm thế nào để sửa chữa android:checkableBehavior? Nếu tôi chọn mục cuối cùng trong nhóm2 và nhấp vào một mục của nhóm1 trở đi, cả hai mục đều được đánh dấu. @espinchi bạn có thể thêm giải pháp cho vấn đề này vào câu trả lời của mình không?
Tomblarom

3
Làm thế nào để áp dụng menu này cho NavigationDrawer?
Yar

@ GabrielGómez cái này xấu quá. Tại sao id bắt buộc phải hiển thị dấu phân cách, nó rất tệ ...
25

rất vui vì tôi đã tìm thấy điều này, không cần phải sử dụng công việc hack mà tôi đã có trước đây.
lasec0203

7

Để phân tách các mục menu bằng một đường phân cách, chỉ nhóm các mục có id duy nhất như ví dụ sau:

activity_main_drawer.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:showIn="navigation_view">

    <item
        android:id="@+id/nav_apps_and_games"
        android:icon="@drawable/ic_apps_black_24dp"
        android:title="@string/my_apps_and_games" />

    <item
        android:id="@+id/nav_bookmarked_apps"
        android:icon="@drawable/ic_add_bookmark_black_24dp"
        android:title="@string/bookmarked_apps" />

    <item
        android:id="@+id/nav_manage_downloads"
        android:icon="@drawable/ic_downloading_file_black_24dp"
        android:title="@string/manage_downloads" />

    <!-- SET A UNIQUE ID TO THE BELOW GROUP -->
    <group android:id="@+id/group1">

        <item
            android:id="@+id/nav_settings"
            android:icon="@drawable/ic_settings_black_24dp"
            android:title="@string/settings" />

        <item
            android:id="@+id/nav_sign_up"
            android:icon="@drawable/ic_card_membership_black_24dp"
            android:title="@string/sign_up_login" />

    </group>

</menu>

Kết quả trực quan:

nhập mô tả hình ảnh ở đây


2

Phương pháp hacky của tôi tương tự như của Mostrapotski.

Trong Bố cục cho bộ điều hợp tùy chỉnh của tôi, tôi đang thêm dấu phân cách ngang ở đầu mỗi mục và đặt chế độ hiển thị của nó thành biến mất.

Đối với các phần tử đánh dấu sự bắt đầu của một nhóm mới, tôi đặt khả năng hiển thị của chúng thành hiển thị để dấu phân tách hiển thị trên đầu nhóm.


1

Bạn có hai sự lựa chọn

  1. Các mục của bạn có thể được tách biệt (danh sách ở trên cùng và chế độ xem cổ điển ở dưới cùng). Sau đó, thay vì chế độ xem danh sách trong bố cục chính của bạn (android: id = "@ + id / left_drawer"), bạn có thể có một LinearLayout khá phức tạp bao gồm 3 mục đó (danh sách, dấu phân cách và chế độ xem dưới cùng)
  2. Các mục của bạn phải chính xác như trong ví dụ của bạn, sau đó bạn cần dấu phân tách trong danh sách, bạn có thể sử dụng một số logic trong bộ điều hợp của mình để vẽ chế độ xem trên đầu mục danh sách nơi bạn cần dấu phân tách. (nghĩa là mục danh sách của bạn sẽ không còn là một chế độ xem văn bản đơn lẻ nữa mà là một LinearLayout với dấu phân tách đã biến mất (và đôi khi hiển thị, theo logic của bộ điều hợp của bạn).

Để giúp bạn với một số mã mẫu, bạn có thể vui lòng đăng tất cả các món bạn cần trong menu của mình được không? Chúng ta cần biết chính xác những gì sẽ là tĩnh và những gì sẽ có thể cuộn được.

Chỉnh sửa : Nếu bạn muốn nó hoạt động với exemple, hãy loại bỏ dòng

mDrawerList.setAdapter(new ArrayAdapter<String>(this, ...)

Bạn cần cung cấp bộ điều hợp sản xuất tại nhà như sau: https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView

Như tôi đã nói ở phần 2, trong bộ điều hợp của bạn, bạn sẽ có logic và do đó bạn có thể nói trong phương thức getView ()

if(myPlanet.isNeptune()) 
    holder.mSepatator.setVisibility(View.VISIBLE);
else 
    holder.mSepatator.setVisibility(View.GONE);

Đây là đoạn mã chính mà tôi đang sử dụng. Phần còn lại là tất cả các tệp xml như string.xml ...
Redson

Có nhưng đây là mẫu Android cho bố cục ngăn kéo, BẠN sẵn sàng có gì?
Mostrapotski
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.