8

I need change the space between header group and first item menu, here's an example:

enter image description here

I have seen a lot of examples and posts but only be can change the space for all items, and I just need to change only for header group.

Any idea?

azizbekian
  • 60,783
  • 13
  • 169
  • 249
Gaston Flores
  • 2,457
  • 3
  • 23
  • 42

4 Answers4

9

There are 4 types of items in the RecyclerView that NavigationView creates:


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
            case VIEW_TYPE_NORMAL:
                return new NormalViewHolder(mLayoutInflater, parent, mOnClickListener);
            case VIEW_TYPE_SUBHEADER:
                return new SubheaderViewHolder(mLayoutInflater, parent);
            case VIEW_TYPE_SEPARATOR:
                return new SeparatorViewHolder(mLayoutInflater, parent);
            case VIEW_TYPE_HEADER:
                return new HeaderViewHolder(mHeaderLayout);
        }
        return null;
    }

The one you are interested in is SubheaderViewHolder. R.layout.design_navigation_item_subheader is the layout, that would be inflated for that ViewHolder.

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="?attr/listPreferredItemHeightSmall"
          android:gravity="center_vertical|start"
          android:maxLines="1"
          android:paddingLeft="?attr/listPreferredItemPaddingLeft"
          android:paddingRight="?attr/listPreferredItemPaddingRight"
          android:textAppearance="@style/TextAppearance.AppCompat.Body2"
          android:textColor="?android:textColorSecondary"/>

As you can see, the height is taken from the theme's listPreferredItemHeightSmall attribute. But you cannot achieve your requirement just by changing the value of listPreferredItemHeightSmall, because NormalViewHolder's item is also dependent on that value, thus changing it would affect all other items too.

The sneaky and non-reliable way of achieving that would be to acquire this RecyclerView on runtime with getIdentifier() API. The id of the custom RecyclerView is design_navigation_view. Once acquired, you can manually get the actual View from RecyclerView (knowing which child of RecyclerView is the one you need). Then you can manually change the height of that View. But that is not reliable, because:

  • It won't be easy to handle that for many such items, because you cannot know how many of them are actually displayed (well, you can, but is it worth it?)

  • You have to listen for scroll events and detect when any new SubheaderViewHolder is getting displayed - then apply your custom height.

I cannot find enough seams to affect the height of that item. Your best option would be to provide your custom layout as the content of NavigationView.

azizbekian
  • 60,783
  • 13
  • 169
  • 249
  • You are a genius!, because with the info that you give me about design_navigation_item_subheader, I found a solution for my problem. Basically I create a layout with the same name and I change de padding that I need. Thanks a lot! – Gaston Flores Jun 05 '17 at 00:04
3

Thanks to azizbekian, his answer gived to me a great idea (maybe not the best but in my case more simple and fast to implement). Basically, I add a layout with the same name (this will override it). After that I change all that I need, so the result is this:

enter image description here

enter image description here

Gaston Flores
  • 2,457
  • 3
  • 23
  • 42
2

In my experience, the best way to handle nav drawer is to have it display a full Fragment. This allows you to have a total control of its layout and behavior.

Vasiliy
  • 16,221
  • 11
  • 71
  • 127
  • I understand, but I have not time and resources for do a refactor on this component. I try to find a workaround (a hack), I know that I can get the recyclerView from the NavigationView with this code `(RecyclerView) ((NavigationView) findViewById(R.id.navigation)).getChildAt(0);`, so my plan is get the view from each viewholder from recycler, but for the moment I could not do it. Have you ever done this? – Gaston Flores Jun 03 '17 at 23:54
-1

Changing the values in dimen.xml by overriding the values which are already set in the android support library.

 <dimen name="design_navigation_padding_top_default"
tools:override="true">0dp</dimen>
<dimen name="design_navigation_separator_vertical_padding"tools:override="true">0dp</dimen>
<dimen name="design_navigation_padding_bottom"tools:override="true">0dp</dimen>
Akshay Nandwana
  • 1,260
  • 11
  • 18
  • This override the padding between all rows. This does not work for me, I need only change the space in the section that was marked on the screenshot. – Gaston Flores Jun 03 '17 at 19:48
  • @GastonFlores yes, same way we can find the margin value from the library between header and it's first item and change it's value. – Akshay Nandwana Jun 04 '17 at 00:08
  • @GastonFlores I think [this](https://github.com/android/platform_frameworks_support/blob/master/design/res/values/dimens.xml) will help you achieve what you want. Overriding the values directly from the library. – Akshay Nandwana Jun 04 '17 at 08:47