Как установить заголовок NavigationView с помощью Anko DSL?

В общем формате XML основной макет по умолчанию выглядит так:

<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="match_parent" /> <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header_main" app:menu="@menu/activity_main_drawer" /> </android.support.v4.widget.DrawerLayout> 

Я попытался закодировать это с помощью Anko DSL:

 ... override fun createView(ui: AnkoContext<MainActivity>) = with(ui) { drawerLayout { lparams(width = matchParent, height = matchParent) id = ID_DRAWER_LAYOUT fitsSystemWindows = true navigationView { lparams(width = wrapContent, height = matchParent) id = ID_NAVIGATION_VIEW foregroundGravity = Gravity.START fitsSystemWindows = true addHeaderView(navHeaderView()) //// PROBLEM HERE //// inflateMenu(R.menu.activity_main_drawer) } } } private fun ViewGroup.navHeaderView() { linearLayout { lparams(width = matchParent, height = dip(160)) backgroundResource = R.drawable.side_nav_bar gravity = Gravity.BOTTOM orientation = LinearLayout.VERTICAL setPadding(dip(64), dip(16), dip(64), dip(16)) imageView { id = ID_IMAGE_VIEW topPadding = dip(16) imageResource = android.R.drawable.sym_def_app_icon } textView { lparams(width = matchParent, height = wrapContent) id = ID_TEXT_NAME topPadding = dip(16) text = "test1" if (Build.VERSION.SDK_INT >= 23) { setTextAppearance(R.style.TextAppearance_AppCompat_Body1) } else { setTextAppearance(context, android.R.style.TextAppearance_Medium) } } textView { id = ID_TEXT_DESCRIPTION text = "test2" } } } ... 

Отмеченная строка генерирует исключение, говоря, что представление уже имеет родительский элемент.


Затем я попытался использовать плагин Anko DSL Preview для автоматического преобразования xml, он просто сделал это, не полностью изменив его на Anko DSL:

 android.support.v4.widget.DrawerLayout { id = Ids.drawer_layout include<View>(R.layout.app_bar_main).lparams(width = matchParent, height = matchParent) org.mewx.projectprpr.template.NavigationFitSystemView { id = Ids.nav_view app:headerLayout = @layout/nav_header_main //// HERE //// app:menu = @menu/activity_main_drawer }.lparams(width = wrapContent, height = matchParent) } 

Как добавить заголовок с помощью Anko DSL?

Благодаря!

Во-первых, DrawerLayout в своем конструкторе проверяет fistSystemWindows и устанавливает фон состояния, поэтому, к сожалению, самый простой способ использования DrawerLayout с fitsSystemWindows – раздуть его из XML.

Во-вторых, методы Anko DSL не просто создают новые представления, но также присоединяют их к родителям. Вы должны создать отдельный вид:

 addHeaderView(UI { navHeaderView() }.view) 

Этот код предназначен для использования с Anko 0.10.0-beta-2 , поведение и даже синтаксис могут отличаться от версии к версии.

В-третьих, я поймал ошибку: когда я открываю ящик, пока отображается клавиатура, заголовок имеет большое нижнее дополнение (вставка). Мое печальное обходное решение выглядит так:

 addHeaderView( object : _RelativeLayout(context) { // fixes bottomPadding with open keyboard :'( @TargetApi(20) override fun onApplyWindowInsets(insets: WindowInsets) = insets.consumeSystemWindowInsets() }.apply { /* DSL code here */ })