anko icon indicating copy to clipboard operation
anko copied to clipboard

Splitting a layout into smaller functions

Open nkanellopoulos opened this issue 7 years ago • 4 comments

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

nkanellopoulos avatar Jul 04 '17 14:07 nkanellopoulos

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?

nkanellopoulos avatar Jul 07 '17 14:07 nkanellopoulos

Best since sliced bread!

Abegemot avatar Feb 20 '18 11:02 Abegemot

just use command+option+M in Android Studio ~

zhangqixiang-sh avatar May 31 '18 06:05 zhangqixiang-sh

@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 !

s4cha avatar Nov 21 '18 16:11 s4cha