Is it possible to reuse the layout in Kotlin Anko

I read that the greatest advantage of using Anko is its reuse. But I could not find his exact example.

Currently, in the new Android layout system, the boiler stove is as follows:

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

From the layout structure above, only <The Main Content> is varry. And also in many cases, this ceremonial setting is duplicated in almost every action.

So here, when Anko thinks, is there a reusable solution to this problem. I do not expect it to be reused for general purposes, but at least I can minimize the ceremonial code in the project. Maybe I need something like:

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

From the above code, im expecting myCustomRootLayout will do all the ceremonial setup for a root layout such as (DrawerLayout, CoordinatorLayout, etc. etc.).

Is it possible?

EDIT Therefore, I think my question is: How to create a custom component that can host another component

+7
android android-layout kotlin anko
source share
2 answers

One way to reuse the code is to simply extract myCustomRootLayout into the extension method, for example:

 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() } } 

However, as indicated in the documentation :

Although you can directly use DSL (in onCreate() or everywhere else) without creating additional classes, it is often convenient to have a user interface in a separate class. If you use the provided AnkoComponent interface, you also get the DSL layout preview feature for free.

It seems like a good idea to extract the reusable part into a separate 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() } } } 
+3
source share

I really found a way to do this, took me a while to figure it out.

I have a basic test layout, the content is added to the RelativeLayout .

The key here is to add your own layout in the delegated AnkoContext , which delegates to the immediate parent ( RelativeLayout in my case).

 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) } } } } 

And then you can extend BaseAnkoComponent and create your content in the same way using Anko DSL.

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

I am sure there is a better way to do this, but I have not found it. New for Kotlin and Anko.

+3
source share

All Articles