inflaterでの縦横レイアウト自動切り替え


■AndroidManifest
android:configChanges を設定

■Activity
protected View targetLayout;
protected LayoutInflater inflater;

/**
* 画面を切り替えたときの挙動
*/
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setPortrait();
} else {
setLandscape();
}
}

/**
* 縦画面設定
*/
public void setPortrait() {
if (inflater == null)
inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
targetLayout = inflater.inflate(R.layout.<レイアウトファイル指定>, null);
changeLayout(findViewById(R.id.<対象のレイアウトのID指定>));
}

/**
* 横画面設定
*/
public void setLandscape() {
if (inflater == null)
inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
targetLayout = inflater.inflate(R.layout.<レイアウトファイル指定>, null);
changeLayout(findViewById(R.id.<対象のレイアウトのID指定>));
}

/**
* targetLayoutに設定されているRelativeLayout.LayoutParamsの内容を、
* 同じIDをもつsourceViewを含むすべての子Viewにコピーする
*
* @param sourceView
*/
public void changeLayout(View sourceView) {
View targetView = targetLayout.findViewById(sourceView.getId());
if (targetView != null) {
if (sourceView.getLayoutParams() instanceof RelativeLayout.LayoutParams) {
RelativeLayout.LayoutParams sourceLayoutParams = (RelativeLayout.LayoutParams)sourceView
.getLayoutParams();
RelativeLayout.LayoutParams targetLayoutParams = (RelativeLayout.LayoutParams)targetView
.getLayoutParams();
for (int i = 0; i < targetLayoutParams.getRules().length; i++) {
sourceLayoutParams.addRule(i, targetLayoutParams.getRules()[i]);
}
sourceLayoutParams.width = targetLayoutParams.width;
sourceLayoutParams.height = targetLayoutParams.height;
sourceLayoutParams.leftMargin = targetLayoutParams.leftMargin;
sourceLayoutParams.rightMargin = targetLayoutParams.rightMargin;
sourceLayoutParams.topMargin = targetLayoutParams.topMargin;
sourceLayoutParams.bottomMargin = targetLayoutParams.bottomMargin;
sourceLayoutParams.alignWithParent = targetLayoutParams.alignWithParent;

} else if (sourceView.getLayoutParams() instanceof LinearLayout.LayoutParams) {
LinearLayout.LayoutParams sourceLayoutParams = (LinearLayout.LayoutParams)sourceView
.getLayoutParams();
LinearLayout.LayoutParams targetLayoutParams = (LinearLayout.LayoutParams)targetView
.getLayoutParams();
sourceLayoutParams.width = targetLayoutParams.width;
sourceLayoutParams.height = targetLayoutParams.height;
sourceLayoutParams.leftMargin = targetLayoutParams.leftMargin;
sourceLayoutParams.rightMargin = targetLayoutParams.rightMargin;
sourceLayoutParams.topMargin = targetLayoutParams.topMargin;
sourceLayoutParams.bottomMargin = targetLayoutParams.bottomMargin;
sourceLayoutParams.weight = targetLayoutParams.weight;
sourceLayoutParams.gravity = targetLayoutParams.gravity;
}
}
if (sourceView instanceof ViewGroup) {
ViewGroup sourceViewGroup = (ViewGroup)sourceView;
for (int i = 0; i < sourceViewGroup.getChildCount(); i++) {
changeLayout(sourceViewGroup.getChildAt(i));
}
}
}

毎回実装するのがめんどくさいのでメモ
■■■■■■■■■追記■■■■■■■■■
上記実装を行うとUIと端末状態によってはメモリーリークが発生する

なので下記処理を実装するとよいことが起きる。

@Override
public void onDestroy() {
super.onDestroy();
cleanUpDrawable(findViewById(R.id.<対象のレイアウトのID指定>));
}

/**
* Bitmapのメモリリーク対策
*
* @param view トップレベルのViewを指定
*/
public static final void cleanUpDrawable(View view) {
if (view == null) {
return;
}

// 全View共通
view.setBackgroundDrawable(null);

// 各種View個別
if (view instanceof ImageView) {
ImageView iv = (ImageView)view;
iv.setImageDrawable(null);
} else if (view instanceof ImageButton) {
ImageButton ib = (ImageButton)view;
ib.setImageDrawable(null);
} else if (view instanceof SeekBar) {
SeekBar sb = (SeekBar)view;
sb.setProgressDrawable(null);
sb.setThumb(null);
} else {
// 追加予定
}

// 子Viewに再帰的に適用
if (view instanceof ViewGroup) {
ViewGroup vg = (ViewGroup)view;
int count = vg.getChildCount();
for (int i = 0; i < count; i++) {
cleanUpDrawable(vg.getChildAt(i));
}
}
}