public void view() {
linearLayout(() -> {
button(() -> { // Inside any view block...
init(() -> { // you may declare "init" function and pass lambda into it
Button b = Anvil.currentView(); // Type of a view is deduced automatically in most cases
mButton = (Button) Anvil.currentView(); // Or you may cast it explicitly
// You are not forced to do this within "init" block, but otherwise your code will be called on every rendering cycle
})
});
});
}
// later on you may use mButton as a normal view:
mButton.performClick();
button(() -> {
id(MY_BUTTON);
});
// later just find view by ID, IIRC Android caches views and their IDs:
findViewByID(MY_BUTTON).performClick();
No, in Anvil there are two forms of DSL:
One is for Java 8 and Kotlin, where you pass lambdas. Here functions return void
.
Another is for Java 6 and it uses a trick which makes it look similar to Mithril:
o (linearLayout(),
size(FILL, FILL),
o (button(),
size(FILL, WRAP),
onClick(someHandler)),
o (button(),
size(FILL, WRAP),
text(someText),
onClick(someOtherHandler)));
o
in this case looks like a bullet point in the list, so the whole layout (if nicely indented) looks like a tree of view items.
In this case to tell views from attributes in the function parameters some functions return some special types to make the compiler check for the types. But again, they don't return actual views. The only way to get a view instance is to use Anvil.currentView()
. Good news is that you can use it anywhere in you code (e.g. in other methods), as long as your code is called from within the view()
function.
This is what I attempted:
class HelloView(c: Context, constraint: ConstraintLayout) : RenderableView(c) {
val constraint: ConstraintLayout
init {
this.constraint = constraint
}
override fun view() {
textView {
text(R.string.login_title)
val title: TextView = Anvil.currentView()
this.constraint.addView(title)
}
}
}
class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val constraint = ConstraintLayout(this)
setContentView(HelloView(this, constraint))
}
}
However that will error saying, java.lang.IllegalStateException: The specified child already has a parent. You must call removeView()
which I understand.
constraint
to anything
class ContactView(c: Context) : RenderableView(c) {
override fun view() {
textView {
text("Contact Title")
}
}
}
class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val constraintLayout = ConstraintLayout(this)
constraintLayout.id = 1
setContentView(constraintLayout)
val contactUs = ContactView(this)
val clpcontactUs = ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT)
constraintLayout.addView(contactUs)
val constraintSet = ConstraintSet()
constraintSet.clone(constraintLayout)
constraintSet.constrainWidth(contactUs.id, ConstraintSet.WRAP_CONTENT)
constraintSet.centerHorizontally(contactUs.id, constraintLayout.id)
constraintSet.connect(contactUs.id, ConstraintSet.TOP, constraintLayout.id, ConstraintSet.TOP, 68)
constraintSet.applyTo(constraintLayout)
ConstraintSet.LEFT
, it doesn't work, but apparently does in XML. https://issuetracker.google.com/issues/62154545