FrameLayoutでsetMarginを使う

iPhoneのアプリをAndroidに移植する作業をしています。

iPhoneのUIは基本的に位置をドット単位(厳密には違うが)で指定するため、AbsoluteLayout亡き今、Androidではなかなか任意の位置にViewを配置するのは難しい。

とりあえずよくある手法は、LayoutParamsでサイズと位置を設定するもの。こんな感じ。

public void setViewFrame(View view, Rect rect) {
Rect newRect = convertVirtualRectToRealRect(rect); //iOSでの座標指定からAndroidの現解像度にあうよう座標変換する
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(newRect.width(), newRect.height());
params.setMargins(newRect.left, newRect.top, 0, 0);
view.setLayoutParams(params);
}

しかし、何故かこれではうまくいかない。

色々試行錯誤した結果、以下のように、

public void setViewFrame(View view, Rect rect) {
Rect newRect = convertVirtualRectToRealRect(rect);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(newRect.width(), newRect.height());
params.gravity = Gravity.NO_GRAVITY; // <--必須!
params.setMargins(newRect.left, newRect.top, 0, 0);
view.setLayoutParams(params);
}

LayoutParamsのインスタンスのgravityプロパティにGravity.NO_GRAVITYを設定する事で解決。

なお、これは2.xくらいでの話で、4.0ではこの処置をしなくても問題無かった。でもやっておいたほうが良かろう。

こちらの記事もどうぞ