是否可以在 Kotlin Anko 中重用布局
Posted
技术标签:
【中文标题】是否可以在 Kotlin Anko 中重用布局【英文标题】:Is it possible to reuse a layout in Kotlin Anko 【发布时间】:2017-02-25 21:08:03 【问题描述】:我读到使用 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 一起思考是否有关于该问题的可重用解决方案。我不希望它可重复用于通用布局,但至少我可以最小化项目中的仪式代码。也许我需要类似的东西:
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 等)。
这可能吗?
编辑 所以我认为我的问题是:如何制作可以托管其他组件的自定义组件
【问题讨论】:
【参考方案1】:重用代码的一种方法是简单地将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()
或任何地方 否则),无需创建任何额外的类,通常很方便 在单独的类中有 UI。如果您使用提供的 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()
【讨论】:
感谢您的回复。是的,我明白这一点。但可以找到如何制作作为其他组件容器的自定义组件的示例。查看我的代码,myCustomRootLayout
应该包含 DrawerLayout, CoordinatorLayout, AppBarLayout
等,但还应该托管另一个组件 <The Main Content>
。所以将来我可以像这样使用它们:myCustomRootLayout recyclerView()
(在其中添加一个回收器视图)
@ktutnik myCustomRootLayout
扩展方法和MyCustomRootLayout
类都接受在设置组件元素后调用的委托。此委托可用于添加自定义子元素,即recyclerView()
我担心插入的孩子的位置。是否需要付出一些努力才能将孩子作为 CoordinatorLayout 的孩子而不是根视图?
@ktutnik 我有一个几乎相同的问题。您是否找到将自定义视图作为子项插入另一个布局的方法?
@SuhairZain:抱歉还是找不到路。【参考方案2】:
我实际上找到了一种方法来做到这一点,花了我一段时间才弄明白。
我在这里有一个非常基本的测试布局,内容被添加到
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
并以与 Anko DSL 相同的方式构建您的内容。
class FooActivityUi : BaseAnkoComponent<FooActivity>()
override fun <T> AnkoContext<T>.content(): View?
return verticalLayout
lparams(width = matchParent, height = matchParent)
button("Hello")
textView("myFriend")
我确信有更好的方法可以做到这一点,但我还没有找到。对 Kotlin 和 Anko 来说有点陌生。
【讨论】:
以上是关于是否可以在 Kotlin Anko 中重用布局的主要内容,如果未能解决你的问题,请参考以下文章
在Android中用Kotlin的Anko运行后台任务(KAD 09)
如何在 Kotlin 中使用 anko 删除除最新 10 条记录之外的所有记录?
用Anko和Kotlin实现Android上的对话框和警告提示(KAD 24)
AnKo SQLite:从数据库中异步填充listview?
Kotlin/Anko/OpenCV/CameraView 无法创建处理程序,因为线程尚未调用 Looper.prepare()