According to the Android View
documentation View(Context)
is used when constructed from code and View(Context, AttributeSet)
and View(Context, AttributeSet, int)
(and since API level 21 View(Context, AttributeSet, int, int)
) are used when the View
is inflated from XML.
The XML constructor all just call the same constructor, the one with the most arguments which is the only one with any real implementation, so we can use default arguments in Scala. The "code constructor" on the other hand may have another implementation, so it is better to actually call in from Scala as well.
The following implementation may be a solution:
private trait MyViewTrait extends View {
// implementation
}
class MyView(context: Context, attrs: AttributeSet, defStyle: Int = 0)
extends View(context, attrs, defStyle) with MyViewTrait {}
object MyView {
def apply(context: Context) = new View(context) with MyViewTrait
}
The "code constructor" may then be used like:
var myView = MyView(context)
(not a real constructor).
And the other once like:
var myView2 = new MyView(context, attrs)
var myView3 = new MyView(context, attrs, defStyle)
which is the way the SDK expects them.
Analogously for API level 21 and higher the class
can be defined as:
class MyView(context: Context, attrs: AttributeSet, defStyle: Int = 0, defStyleRes: Int = 0)
extends View(context, attrs, defStyle, defStyleRes) with MyViewTrait {}
and the forth constructor can be used like:
var myView4 = new MyView(context, attrs, defStyle, defStyleRes)
Update:
It gets a bit more complicated if you try to call a protected
method in View
, like setMeasuredDimension(int, int)
from the trait
. Java protected methods cannot be called from traits. A workaround is to implement an accessor in the class
and object
implementations:
private trait MyViewTrait extends View {
protected def setMeasuredDimensionAccessor(w: Int, h: Int): Unit
def callingSetMeasuredDimensionAccessor(): Unit = {
setMeasuredDimensionAccessor(1, 2)
}
}
class MyView(context: Context, attrs: AttributeSet, defStyle: Int = 0)
extends View(context, attrs, defStyle) with MyViewTrait {
override protected def setMeasuredDimensionAccessor(w: Int, h: Int) =
setMeasuredDimension(w, h)
}
object MyView {
def apply(context: Context) = new View(context) with MyViewTrait {
override protected def setMeasuredDimensionAccessor(w: Int, h: Int) =
setMeasuredDimension(w, h)
}
}