anko
anko copied to clipboard
Splitting a layout into smaller functions
I tried to factor out a part of my layout into a separate function. But I am getting an exception.
Being able to split the layout definition is very useful, so I guess I am doing something wrong?
I have also tried to return a View from my test()
function, which did not work either.
See below for the exception thrown by Android.
class GenericRecyclerUI(val dataAdapter: RecyclerView.Adapter<GenericRecyclerViewHolder>) : AnkoComponent<Fragment> {
override fun createView(ui: AnkoContext<Fragment>): View {
return with(ui) {
val c = (ui.owner as GenericRecyclerFragment).configuration // config object
verticalLayout {
if (c.showHeader) {
textView {
padding = dip(5)
backgroundColor = resources.getColor(c.headerBackground)
text = c.headerTitle
typeface = Typeface.DEFAULT_BOLD
textSize = 22f
textColor = Color.WHITE
textAlignment = View.TEXT_ALIGNMENT_GRAVITY
gravity = Gravity.CENTER
}.lparams {
width = matchParent
height = c.headerHeight
bottomMargin = dip(3)
}
}
test(this@with)
frameLayout {
lparams(width = matchParent, height = matchParent)
val recycler = recyclerView {
id = R.id.ui_grv_recycler
lparams(width = matchParent, height = matchParent)
layoutManager = LinearLayoutManager(ctx)
adapter = dataAdapter
}
}
}
}
}
private fun test(ui: AnkoContext<Fragment>) {
with(ui) {
editText() {
textSize = 20f
}
}
}
}
This code throws an exception: Caused by: java.lang.IllegalStateException: View is already set: 0,0-0,0} at org.jetbrains.anko.AnkoContextImpl.alreadyHasView(AnkoContext.kt:118) at org.jetbrains.anko.AnkoContextImpl.addView(AnkoContext.kt:100) at org.jetbrains.anko.internals.AnkoInternals.addView(Internals.kt:48) at org.example.ui.GenericRecyclerUI.createView(GenericRecyclerFragment.kt:286) at org.example.ui.GenericRecyclerFragment.onCreateView(GenericRecyclerFragment.kt:218) at android.support.v4.app.Fragment.performCreateView(Fragment.java:2192) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1255) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1472) at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1691) at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:3440) at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:120) at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:378) at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:33) at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:79) at android.view.LayoutInflater.createViewFromTag
To answer my own question, the problem here is that the receiver is actually _LinearLayout
.
So adding an extension method to _LinearLayout does the job.
private fun _LinearLayout.test2() {
editText {
textSize = 20f
}.lparams {
width = matchParent
height = dip(40)
}
}
However, could this be done without adding a method to _LinearLayout
?
Best since sliced bread!
just use command+option+M
in Android Studio ~
@nkanellopoulos I had the same issue and here is my take on it
fun foodTypeFilter(vm: ViewManager, wording: String): View {
return vm.run {
relativeLayout {
button(wording).lparams {
alignParentBottom()
centerHorizontally()
}
backgroundColor = Color.GRAY
elevation = dip(10).toFloat()
}
}
}
// later... in side of createView(ui: AnkoContext<FoodFragment>): View {
foodTypeFilter(this, "Croquettes".toUpperCase())
Essentially passing this in the function, the param being an abstract "ViewManager"
Hope this helps !