以下を実装するカスタム ビューを作成しましたonMeasure
。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
float width = MeasureSpec.getSize(widthMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
float height = MeasureSpec.getSize(heightMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
float nominalHeight = getResources().getInteger(R.integer.nominalheight);
float nominalWidth = getResources().getInteger(R.integer.nominalwidth);
float aspectRatio = nominalWidth / nominalHeight;
if( width / height > aspectRatio //too wide
&& (
widthMode == MeasureSpec.AT_MOST ||
widthMode == MeasureSpec.UNSPECIFIED
)
) {
width -= (width - height * aspectRatio);
}
if( width / height < aspectRatio //too tall
&& (
heightMode == MeasureSpec.AT_MOST ||
heightMode == MeasureSpec.UNSPECIFIED
)
) {
height -= (height - width / aspectRatio);
}
setMeasuredDimension((int)width, (int)height);
}
意図は、可能であれば、 および で指定されたものと同じ縦横比を持つ長方形を作成することnominalheight
ですnominalwidth
。明らかに、関数が渡された場合MeasureSpec.EXACTLY
、その方向に指定された次元でレイアウトする必要があります。
これをView
xmlWRAP_CONTENT
で両方向に配置しています。私を困惑させているのは、onMeasure 呼び出しをステップ実行すると、半分が MeasureSpec.AT_MOST を示し、ルーチンが正しい長方形を計算し、残りの半分が MeasureSpec.EXACTLY を示し、明らかに指定された寸法を使用することです。さらに不可解なことに、条件を無効にすると (ドキュメントとサンプルコードから、間違っていると思います)、正常に動作します。
異なる値でこれらの呼び出しが交互に行われるのはなぜですか? また、ビューを正しいサイズで配置するように Android を説得するにはどうすればよいですか?