2016-10-17 2 views
7

Я читал, что наибольшее преимущество использования Anko - его повторное использование. Но я не мог найти его точный пример.Возможно ли повторное использование макета в Kotlin Anko

В настоящее время в новой системе Android макета, котел пластины, как показано ниже:

DrawerLayout (with some setup) 
    CoordinatorLayout (with some setup) 
     AppBarLayout (with some setup) 
     ToolBar 
     <The Main Content> 
    NavigationView (with header inflated) 

Из структуры макета выше, только <The Main Content> является varry. И во многих случаях эти церемониальные установки дублировались почти в каждом действии.

Итак, здесь, когда Anko im думает, есть ли многоразовое решение по этой проблеме. Я не ожидаю, что он будет повторно использоваться для общего назначения, но, по крайней мере, я могу свести к минимуму церемониальный код в проекте. Может быть, мне нужно что-то вроде:

class MainUI: AnkoComponent<MainActivity> { 
    override fun createView(ui: AnkoContext<MainActivity>): View{ 
    return with(ui) { 
     myCustomRootLayout { 
      //here is what <The Main Content> will be 
     } 
    } 
    } 
} 

Из кода выше им ожидающих myCustomRootLayout будет делать все церемониальные установки для корневого макета, таких как (DrawerLayout, CoordinatorLayout и т.д. и т.п.).

Возможно ли это?

EDIT Так я думаю, что мой вопрос: Как сделать пользовательский компонент, который может разместить у себя другие компоненты

ответ

3

Одним из способов повторного использования кода, чтобы просто извлечь myCustomRootLayout в метод расширения, как так:

class MainUI: AnkoComponent<MainActivity> { 
    override fun createView(ui: AnkoContext<MainActivity>): View { 
     return with(ui) { 
      myCustomRootLayout { 
       recyclerView() 
      } 
     } 
    } 
} 

fun <T> AnkoContext<T>.myCustomRootLayout(customize: AnkoContext<T>.() -> Unit = {}): View { 
    return relativeLayout { 
     button("Hello") 
     textView("myFriend") 
     customize() 
    } 
} 

Однако, как stated in the documentation:

Хотя вы можете использовать DSL напрямую (в onCreate() или везде еще), без создания каких-либо дополнительных классов, часто бывает удобно, что имеют пользовательский интерфейс в отдельном классе. Если вы используете предоставленный интерфейс AnkoComponent , вы также получаете функцию предварительного просмотра макета DSL бесплатно.

Казалось бы, хорошая идея, чтобы извлечь многоразовые кусок в отдельный AnkoComponent:

class MainUI : AnkoComponent<MainActivity> { 
    override fun createView(ui: AnkoContext<MainActivity>): View { 
     return with(ui) { 
      MyCustomRootLayout<MainActivity>({ 
       recyclerView() 
      }).createView(ui) 
     } 
    } 
} 


class MyCustomRootLayout<T : Context>(val customize: AnkoContext<T>.() -> Unit = {}) : AnkoComponent<T> { 
    override fun createView(ui: AnkoContext<T>) = with(ui) { 
     relativeLayout { 
      button("Hello") 
      textView("myFriend") 
      customize() 
     } 
    } 
} 
+0

спасибо, что ответили.да, я понимаю об этом. но можно найти пример того, как создать пользовательский компонент, который является контейнером другого компонента. См. Мой код, 'myCustomRootLayout' должен содержать' DrawerLayout, CoordinatorLayout, AppBarLayout' и т. Д. И т. Д., Но также должен содержать другой компонент ''. Поэтому в будущем я могу использовать их как: 'myCustomRootLayout {recyclerView()}' (добавление в него ресайклеров) – ktutnik

+0

@ktutnik как метод расширения myCustomRootLayout, так и класс 'MyCustomRootLayout' принимают делегат, который вызывается после настройки элементы элементов. Этот делегат может быть использован для добавления пользовательских дочерних элементов, то есть 'recyclerView()' – miensol

+0

. Соблюдайте позицию вставленного ребенка. Требуются ли какие-либо усилия для того, чтобы дети были детьми как координаторов-координаторов по отношению к корневому представлению? – ktutnik

3

Я на самом деле нашел способ сделать это, мне потребовалось некоторое время, чтобы понять это.

У меня есть базовый тестовый макет здесь, содержимое добавляется к RelativeLayout.

Ключ здесь заключается в том, чтобы добавить свой собственный макет в делегированный AnkoContext, который делегирует непосредственному родительскому объекту (RelativeLayout в моем случае).

abstract class BaseAnkoComponent<T> : AnkoComponent<T> { 

    companion object { 
     val TOOLBAR_ID = View.generateViewId() 
     val COLLAPSING_ID = View.generateViewId() 
     val COORDINATOR_ID = View.generateViewId() 
     val APPBAR_ID = View.generateViewId() 
     val CONTENT_ID = View.generateViewId() 
    } 

    abstract fun <T> AnkoContext<T>.content(ui: AnkoContext<T>): View? 

    override fun createView(ui: AnkoContext<T>) = with(ui) { 
     coordinatorLayout { 
      id = COORDINATOR_ID 
      lparams(matchParent, matchParent) 
      appBarLayout(R.style.AppTheme_AppBarOverlay) { 
       id = APPBAR_ID 
       lparams(matchParent, wrapContent) 
       fitsSystemWindows = true 
       collapsingToolbarLayout { 
        id = COLLAPSING_ID 
        val collapsingToolbarLayoutParams = AppBarLayout.LayoutParams(matchParent, matchParent) 
        collapsingToolbarLayoutParams.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS 
        layoutParams = collapsingToolbarLayoutParams 
        isTitleEnabled = false 
        toolbar { 
         id = TOOLBAR_ID 
         val toolbarLayoutParams = CollapsingToolbarLayout.LayoutParams(matchParent, dimenAttr(R.attr.actionBarSize)) 
         toolbarLayoutParams.collapseMode = CollapsingToolbarLayout.LayoutParams.COLLAPSE_MODE_PIN 
         layoutParams = toolbarLayoutParams 
         minimumHeight = dimenAttr(R.attr.actionBarSize) 
         background = ColorDrawable(colorAttr(R.attr.colorPrimary)) 
         popupTheme = R.style.AppTheme_PopupOverlay 
        } 
       } 
      } 
      with(AnkoContext.createDelegate(relativeLayout { 
       id = CONTENT_ID 
       val relativeLayoutParams = CoordinatorLayout.LayoutParams(matchParent, matchParent) 
       relativeLayoutParams.behavior = AppBarLayout.ScrollingViewBehavior() 
       layoutParams = relativeLayoutParams 
      })) { 
       content(ui) 
      } 
     } 
    } 
} 

И тогда вы можете продлить BaseAnkoComponent и построить свой контент таким же образом, с Анко DSL.

class FooActivityUi : BaseAnkoComponent<FooActivity>() { 
    override fun <T> AnkoContext<T>.content(): View? { 
    return verticalLayout { 
     lparams(width = matchParent, height = matchParent) 
     button("Hello") 
     textView("myFriend") 
    } 
    } 
} 

Я уверен, что есть лучший способ сделать это, но я не нашел его. Новинка для Котлина и Анко.