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

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

目前在新的Android布局系统中,锅炉板如下:

DrawerLayout (with some setup) CoordinatorLayout (with some setup) AppBarLayout (with some setup) ToolBar  NavigationView (with header inflated) 

从上面的布局结构来看,只有是varry。 在很多情况下,这些仪式设置几乎在每个活动中都重复着。

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

 class MainUI: AnkoComponent { override fun createView(ui: AnkoContext): View{ return with(ui) { myCustomRootLayout { //here is what  will be } } } } 

从上面的代码,我期待myCustomRootLayout将做所有的根布局,如(DrawerLayout,CoordinatorLayout等)的仪式设置。

那可能吗?

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

重用代码的一种方法是简单地将myCustomRootLayout提取到扩展方法中,如下所示:

 class MainUI: AnkoComponent { override fun createView(ui: AnkoContext): View { return with(ui) { myCustomRootLayout { recyclerView() } } } } fun  AnkoContext.myCustomRootLayout(customize: AnkoContext.() -> Unit = {}): View { return relativeLayout { button("Hello") textView("myFriend") customize() } } 

但正如文件中所述 :

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

将可重复使用的部分提取到单独的AnkoComponent似乎是一个好主意:

 class MainUI : AnkoComponent { override fun createView(ui: AnkoContext): View { return with(ui) { MyCustomRootLayout({ recyclerView() }).createView(ui) } } } class MyCustomRootLayout(val customize: AnkoContext.() -> Unit = {}) : AnkoComponent { override fun createView(ui: AnkoContext) = with(ui) { relativeLayout { button("Hello") textView("myFriend") customize() } } } 

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

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

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

 abstract class BaseAnkoComponent : AnkoComponent { 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  AnkoContext.content(ui: AnkoContext): View? override fun createView(ui: AnkoContext) = 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相同的方式构建您的内容。

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

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