是否有可能重新使用Kotlin Anko的布局

我读到使用Anko的最大好处是它的可重用性。 但我无法find确切的例子。

目前在新的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。 在很多情况下,这些仪式设置几乎在每个活动中都重复着。

所以在这里与安科即时思考如果有一个可重用的解决scheme关于这个问题。 我不期望它可以重复使用的通用布局,但至less我可以尽量减less项目中的仪式代码。 也许我需要像这样的东西:

 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等)的仪式设置。

那可能吗?

编辑所以我想我的问题是: 如何使一个自定义组件可以承载其他组件

重用代码的一种方法是简单地将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() } } 

但正如文件中所述 :

虽然您可以直接使用DSL(在onCreate()或其他地方),但不需要创build任何额外的类,在单独的类中使用UI通常很方便。 如果您使用提供的AnkoComponent接口,您还可以免费获得DSL布局预览function。

将可重复使用的部分提取到单独的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() } } } 

实际上我find了一个办法来做到这一点,花了我一段时间才弄明白。

我在这里有一个非常基本的testing布局,内容被添加到一个RelativeLayout

这里的关键是将您的自定义布局添加到委托给直接父级(在我的情况RelativeLayout )委托的AnkoContext

 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并以与Anko DSL相同的方式构build您的内容。

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

我相信有一个更好的方法来做到这一点,但我还没有find它。 Kotlin和Anko有点新鲜。