This is a really very good question.
Here's the reason it behaves (from ImageView.onMeasure (int, int) [line 661] ):
// Try adjusting height to be proportional to width if (!done && resizeHeight) { int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) + ptop + pbottom; if (newHeight <= heightSize) { // line 661 heightSize = newHeight; } // line 663 }
What he does is to adjust the height of the view only if the new height based on the aspect ratio of the stretched and adjusted width (in our case, the exact width of the parent view) is less than the adjusted height (which in this view is simply popped native height plus gasket in our case. Let me know if you want me to stop this point further.)
I donβt understand why there is a restriction that the new height should be less. This only makes sense if our heightSize is either EXACTLY or AT_MOST and set to the upper bound. In other cases, this is not necessary for this.
So, instead of the whole fragment from 661 to 663, there should have been another call
heightSize = resolveAdjustedSize(newHeight, mMaxHeight, heightSpec);
to make sure that we are limited only by the height limit (i.e. we got the AT_MOST limit in heightSpec, and the height value in heightSpec is less than the new height. EXACTLY this cannot happen here if we do not use variable width.)
Maybe I missed something. Guys, whoever reads this, comment if you see any flaws , especially if you are part of the Android team at Google :)
PS . As a workaround, I can suggest you implement a custom ImageView and override onMeasure (int, int) to set the bounds of your exact aspect ratio. Let me know if you need help with the actual code.
UPD I'm going to write out names to attract the attention of smart Android guys on Google (I hope the guys have Google Alerts installed): Romain Guy, Roman Nurik, Reto Mayer, please take a look at this discussion.