How to use Anko DSL inside a Fragment?
Asked Answered
K

3

14

The Github wiki page show this example to be used in Activity instance:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    verticalLayout {
        padding = dip(30)
        editText {
            hint = "Name"
            textSize = 24f
        }
        editText {
            hint = "Password"
            textSize = 24f
        }
        button("Login") {
            textSize = 26f
        }
    }
}

How to do the same inside a Fragment?

I tried to put that verticalLayout block in onCreateView but the method cannot be resolved. I have added anko-support-v4 dependency, but still no luck.

Kragh answered 16/11, 2015 at 7:13 Comment(3)
try to navigate to the verticalLayout method. My guess is that it is defined on Activity, so it works inside it, but not outside it.Streptothricin
If what I said is true, than a solution would be to try assigning the layout to an appropriate property. In your example it kind of hangs in the airStreptothricin
@Streptothricin yes, it's only available in Activity. Finally, I've found a workaround, will post the answer soonKragh
K
13

After digging up anko-support-v4 source code plus some trial and errors, I have found a workaround although I'm not sure if it's the right/recommended way. It seems a little undocumented.

A sample from my Fragment code:

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {

    return UI {
        verticalLayout {
            linearLayout {
                avatar = imageView().lparams(width = dip(48), height = dip (48))
                name = textView().lparams(width = 0, weight = 1f)
            }

            linearLayout {
                // ...
            }
        }
    }.toView()
} 

I'm returning layout DSL wrapped in UI { ... }.toView() in Fragment.onCreateView(...)

Kragh answered 17/11, 2015 at 3:28 Comment(3)
I recommend you asking more on the intended use of API at the slack channel, #anko thread: kotlinslackin.herokuapp.com. Because for me this inconsistency seems like a bug, but people there know for sure.Streptothricin
Yes, it is the right way for the current version of Anko (0.7.3).Hyrup
@netimen just return UI{}.viewPiperidine
C
21

With Anko 0.8 you can also use an AnkoComponent, if you want to hold your UI in a separate class so you can reuse it elsewhere.

class FragmentUi<T>: AnkoComponent<T> {
    override fun createView(ui: AnkoContext<T>) = with(ui) {
        verticalLayout {
            // ...
        }
    }
}

You can call it in your fragment onCreateView() by

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View
        = FragmentUi<Fragment>().createView(AnkoContext.create(ctx, this))
Cowbird answered 27/12, 2015 at 5:32 Comment(1)
AnkoContext.create(ctx, this) is deprecated. instead of ctx one should use requireContext()Aerotherapeutics
K
13

After digging up anko-support-v4 source code plus some trial and errors, I have found a workaround although I'm not sure if it's the right/recommended way. It seems a little undocumented.

A sample from my Fragment code:

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {

    return UI {
        verticalLayout {
            linearLayout {
                avatar = imageView().lparams(width = dip(48), height = dip (48))
                name = textView().lparams(width = 0, weight = 1f)
            }

            linearLayout {
                // ...
            }
        }
    }.toView()
} 

I'm returning layout DSL wrapped in UI { ... }.toView() in Fragment.onCreateView(...)

Kragh answered 17/11, 2015 at 3:28 Comment(3)
I recommend you asking more on the intended use of API at the slack channel, #anko thread: kotlinslackin.herokuapp.com. Because for me this inconsistency seems like a bug, but people there know for sure.Streptothricin
Yes, it is the right way for the current version of Anko (0.7.3).Hyrup
@netimen just return UI{}.viewPiperidine
P
7

As of anko 0.8.1 the correct code would be:

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return UI {
        verticalLayout {
            linearLayout {
                // ...
            }
            linearLayout {
                // ...
            }
        }
    }.view
} 
Piperidine answered 21/3, 2016 at 15:55 Comment(1)
it says it want it when the ? in LayoutInflater is deletedSesquicarbonate

© 2022 - 2024 — McMap. All rights reserved.