I eventually achieved this requirement after some more research.
As some here pointed out, the solution given in most places was this (Converted to kotlin):
class SquareButton(context: Context, attrs: AttributeSet) : Button(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val width: Int = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(width, width)
}
}
The problem with MeasureSpec.getSize
in the scenario is that (along with MeasureSpec.getMode
) it contains the sizing "rule" for the width.
In this case: size:(Available size) + mode:(AT_MOST) = the maximum width allowed for the button
The other option is to get the minimum width, already computed by the Button class:
class SquareButton(context: Context, attrs: AttributeSet) : Button(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val width: Int = measuredWidth
setMeasuredDimension(width, width)
}
}
getMeasuredWidth() returns the width measurement set in onMeasure() via setMeasuredDimension().
What is the difference between MeasureSpec.getSize(widthMeasureSpec) and getWidth()?
The measuredWidth property is set to the wrap_content value when calling super.onMeasure
. This is the wanted value for the width and height.