Как сделать заголовок NavigationView липким

Можно ли сделать заголовок липким в библиотеке поддержки дизайна NavigationView?

<android.support.design.widget.NavigationView android:id="@+id/nav_drawer" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/nav_header" app:menu="@menu/nav_drawer" style="@style/navigation_view_drawer" /> 

РЕДАКТИРОВАТЬ:

Мои попытки до сих пор привели к этому

Переопределение виджета NavigationView и добавление нового метода:

 public class CustomNavigationView extends NavigationView { public CustomNavigationView(Context context) { super(context); } public CustomNavigationView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomNavigationView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } // Inflates header as a child of NavigationView, on top of the normal menu public void createHeader(int res) { LayoutInflater inflater = LayoutInflater.from(getContext());; View view = inflater.inflate(res, this, false); addView(view); } 

}

Затем добавив это к onCreate активности:

 CustomNavigationView navigationView = (CustomNavigationView) findViewById(R.id.your_navigation_view); navigationView.createHeader(R.layout.your_header); 

Это достигает желаемого эффекта (если немного взломано), но когда элементы меню находятся ниже заголовка, вы все равно можете щелкнуть их, любые идеи, чтобы исправить это?

После много экспериментов у меня есть что-то, что работает … это очень хаки, и мне бы хотелось услышать любые предложения, которые вам нужно улучшить!

Переопределенное навигационное меню

 public class CustomNavigationView extends NavigationView { public CustomNavigationView(Context context) { super(context); } public CustomNavigationView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomNavigationView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } // Consumes touch in the NavigationView so it doesn't propagate to views below public boolean onTouchEvent (MotionEvent me) { return true; } // Inflates header as a child of NavigationView public void createHeader(int res) { LayoutInflater inflater = LayoutInflater.from(getContext()); View view = inflater.inflate(res, this, false); // Consumes touch in the header so it doesn't propagate to menu items below view.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event){ return true; } }); addView(view); } // Positions and sizes the menu view public void sizeMenu(View view) { // Height of header int header_height = (int) getResources().getDimension(R.dimen.nav_header_height); // Gets required display metrics DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); float screen_height = displayMetrics.heightPixels; // Height of menu int menu_height = (int) (screen_height - header_height); // Layout params for menu LayoutParams params = new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); params.gravity = Gravity.BOTTOM; params.height = menu_height; view.setLayoutParams(params); } 

}

И это в onCreate основной деятельности

 // Inflates the nav drawer CustomNavigationView navigationView = (CustomNavigationView) findViewById(R.id.your_nav_view); navigationView.createHeader(R.layout.your_nav_header); // sizes nav drawer menu so it appears under header ViewGroup parent = (ViewGroup) navigationView; View view = parent.getChildAt(0); navigationView.sizeMenu(view); 

Я знаю, что вопрос старый, но, может быть, я могу помочь кому-то другому.

 <android.support.design.widget.NavigationView android:id="@+id/nav_drawer" style="@style/navigation_view_drawer" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/nav_header" app:menu="@menu/nav_drawer"> <include layout="@layout/nav_header" /> </android.support.design.widget.NavigationView> 

App: headerLayout является избыточным, но требуется.

Отредактировано из ответа Энисиа .
Это упрощено, более стабильно и с поддержкой привязки данных Android.
Кроме того, добавлен API для получения липкого представления заголовка (в случае привязки данных к макету заголовка)

Переопределенное навигационное меню

 // Add this annotation if databinding is enabled @BindingMethods({ @BindingMethod(type = StickyHeaderNavigationView.class, attribute = "app:stickyHeader", method = "setStickyHeader") }) public class StickyHeaderNavigationView extends NavigationView { @Nullable View mStickyHeaderView; public StickyHeaderNavigationView(Context context) { super(context); } public StickyHeaderNavigationView(Context context, AttributeSet attrs) { super(context, attrs); } public StickyHeaderNavigationView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } // Consumes touch in the NavigationView so it doesn't propagate to views below @Override public boolean onTouchEvent(MotionEvent me) { return true; } @Nullable public View getStickyHeaderView() { return mStickyHeaderView; } // Set a header layout as a child of NavigationView public void setStickyHeader(@LayoutRes int res) { if (mStickyHeaderView != null) { removeView(mStickyHeaderView); } LayoutInflater inflater = LayoutInflater.from(getContext()); View view = mStickyHeaderView = inflater.inflate(res, this, false); // Consumes touch in the header so it doesn't propagate to menu items below view.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; } }); addView(view); // Listen to layout update. When ready, we can do #sizeMenu getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener(this, view)); } // Positions and sizes the menu view private void sizeMenu(@NonNull View view, View headerView) { // Height of header int headerHeight = headerView.getHeight(); // Gets required display metrics DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); float screenHeight = displayMetrics.heightPixels; // Height of menu int menuHeight = (int) (screenHeight - headerHeight); // Layout params for menu LayoutParams params = new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); params.gravity = Gravity.BOTTOM; params.height = menuHeight; view.setLayoutParams(params); } // To listen for layout update, that means header height was calculated private static class OnGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener { final WeakReference<StickyHeaderNavigationView> mViewRef; final WeakReference<View> mHeaderView; OnGlobalLayoutListener(@NonNull StickyHeaderNavigationView view, @NonNull View headerView) { mViewRef = new WeakReference<>(view); mHeaderView = new WeakReference<>(headerView); } @Override public void onGlobalLayout() { StickyHeaderNavigationView view = mViewRef.get(); if (view == null) { return; } // Update once only as the header should be fixed size view.getViewTreeObserver().removeOnGlobalLayoutListener(this); View headerView = mHeaderView.get(); if (headerView == null) { return; } // childAt(0) is the navigation menu view.sizeMenu(view.getChildAt(0), headerView); } } } 

Для включения привязки данных
Примените это в своем макете xml

 <StickyHeaderNavigationView ... android:stickyHeader="@{@layout/your_nav_header}" /> 

Для привязки данных не включено
Примените это в onCreate основной деятельности

 // Inflates the nav drawer CustomNavigationView navigationView = (CustomNavigationView) findViewById(R.id.your_nav_view); navigationView.setStickyHeader(R.layout.your_nav_header); 

Почему вы изобрели колесо, Google уже добавила ваше приложение атрибута NavigatoinView : headerLayout = «ваш макет желания здесь», если вы все еще не понимаете здесь код.

 <android.support.design.widget.NavigationView android:id="@+id/navigationview" android:layout_gravity="start" android:layout_width="wrap_content" android:layout_height="match_parent" app:headerLayout="@layout/nav_header_layout" <!-This your header layout wihch is not sticky--> app:menu="@menu/nav_menu_drawer"/> 

Если вы хотите сделать липкой свой макет заголовка, см. Этот источник github здесь . Вкратце я могу сказать, что вы будете реализовывать это с помощью RecyclerVIew, а не NavigationView. Если у вас есть какие-либо вопросы, не стесняйтесь спрашивать меня.