I know I can use an id
attribute with Anko to identify a view:
class MainActivityUI : AnkoComponent<MainActivity> {
override fun createView(ui: AnkoContext<MainActivity>) = with(ui) {
frameLayout {
textView {
id = R.id.text
}
}
}
}
Then obtain it in the Activity
using the find()
function (or by using Kotlin Android Extensions):
class MainActivity : AppCompatActivity() {
private val textView by lazy {
find<TextView>(R.id.text)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
MainActivityUI().setContentView(this)
textView.text = "Hello World"
}
}
But I feel like I am missing something; the only place the README mentions the find
function or Kotlin Android Extensions is in the section titled Supporting Existing Code:
You don't have to rewrite all your UI with Anko. You can keep your old classes written in Java. Moreover, if you still want (or have) to write a Kotlin activity class and inflate an XML layout for some reason, you can use View properties, which would make things easier:
// Same as findViewById(), simpler to use val name = find<TextView>(R.id.name) name.hint = "Enter your name" name.onClick { /*do something*/ }
You can make your code even more compact by using Kotlin Android Extensions.
Which makes it seem like the find
function is only meant for supporting "old" XML code.
So my question is this; is using an id
along with the find
function the correct way of accessing a View
from the Activity
using Anko? Is there a more "Anko" way of handling this? Or am I missing some other benefit of Anko that makes accessing the View
from the Activity
irrelevant?
And a second related question; if this is the correct way of accessing a View
from the Activity
, is there a way of creating an id
resource (i.e. "@+id/"
) from within an AnkoComponent
? Rather than creating each id
in the ids.xml
file.
Do not use id to identify views with Anko DSL! It is unnecessary and useless because Anko was designed to get rid off XML layouts. Instead use this pattern:
Please note the UI class definition:
If you put there your activity class name in brackets then all its public variables become accessible via owner in UI class body so you can assing them there.
But you may put AppCompatActivity easily and make some universal class which might be cloned. In this case use lateinit var mTextView : TextView in the body of UI class as described in Jacob's answer here.
So, why still use
XML id
to locate the View? since we already use the Anko instead of the XML.In my opinion, we can store the view elements inside the
AnkoComponent
instead of thefind view
's id method. Check the code blow:I believe that, as you can add behavior to your Anko files, you don't have to instantiate your views in the activity at all.
That can be really cool, because you can separate the view layer even more. All the code that acts in your views can be inserted in the Anko files. So all you have to do is to call your activity's methods from the Anko and not instantiate any view.
But if you need to instantiate any view... you can use Kotlin Android Extensions in your activity.
Exemple:
Code in your activity:
Code in Anko:
Now the code is in AnkoComponent. No need to instantiate the view.
Conclusion:
It's a more 'Anko' way to program if you put all your view logic in the AnkoComponents, not in your activities.
Edit:
As an exemple of a code where you don't have to instantiate a view:
In your Anko:
In your activity:
This is a very different approach. I'm not so sure if I like it or not, but this is a whole different discussion...
To generalize the question a bit: How can one make an AnkoComponent that is encapsulated, can be used from the DSL and can have its data programmatically set after creation?
Here is how I did it using the View.tag:
}