Viewを追加すると自動で折り返すLayout

動的にViewを追加して横幅を超えたら折り返すLayoutをつくろうとしているがうまくいかない。

http://cheesecomer.blogspot.jp/2012/06/androidsilverlightwrappanelviewgroup.html

↑を参考に書いた。親ViewのonMeasure()で子ViewのRuleを決めるとうまく行かなかったが、親ViewのonMeasure()前に子Viewのmeasure()を走らせRuleを先に設定した後に親ViewのonMeasure()を走らせることでうまく動いた。

以下、ソース。

public class WrapLayout extends RelativeLayout {

	public WrapLayout(Context context) {
		super(context);
	}

	public WrapLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public WrapLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	@Override
	public void addView(View child) {
		// idが未設定の場合は乱数でどうにかする。
		if (child.getId() == -1) {
			child.setId(new Random(System.currentTimeMillis()).nextInt(Integer.MAX_VALUE));
		}

		super.addView(child);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		int l = this.getChildCount();
		if (l > 0) {
			int max = MeasureSpec.getSize(widthMeasureSpec);
			View pline = this.getChildAt(0);
			View prev = this.getChildAt(0);
			prev.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
			int currentTotal = pline.getMeasuredWidth();
			for (int i = 1; i < l; i++) {
				View child = this.getChildAt(i);
				child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
				int width = child.getMeasuredWidth();
				RelativeLayout.LayoutParams layoutParams =
						(RelativeLayout.LayoutParams) child.getLayoutParams();
				if (max > currentTotal + width) {
					currentTotal += width;
					layoutParams.addRule(RelativeLayout.ALIGN_TOP, prev.getId());
					layoutParams.addRule(RelativeLayout.RIGHT_OF, prev.getId());
				} else {
					layoutParams.addRule(RelativeLayout.BELOW, pline.getId());
					layoutParams.addRule(RelativeLayout.ALIGN_LEFT, pline.getId());
					pline = child;
					currentTotal = pline.getMeasuredWidth();
				}
				prev = child;
			}
		}

		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
}

雑感

めんどくさい。よくあるViewの形なんだから標準のLayoutに合ってもいいと思うんだけどなぁ。。。