Yesterday, a post came over the transom on the [android-developers] Google Group, citing a problem in getting a RelativeLayout to work properly as a row in a ListView. Since I screwed up my initial response to that post, I figured I’d document and write up a blow-by-blow account of the diagnostic steps I went through to in order to determine what is going wrong.
To give you a clue as to the final outcome, the subtitle of this post should be “How I Learned to Stop Worrying And Love the Box Model”…
First, here is his original row layout (with only some reformatting applied):
[sourcecode lang=”xml”]
[/sourcecode]
I put together my own test scaffold activity to use this row:
[sourcecode lang=”java”]
public class DiagnosticDemo extends ListActivity {
String[] items={“lorem”, “ipsum”, “dolor”};
static int ROW_TO_TEST=R.layout.row_original;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new TestAdapter(this));
}
class TestAdapter extends ArrayAdapter {
Activity context;
TestAdapter(Activity context) {
super(context, ROW_TO_TEST, items);
this.context=context;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=context.getLayoutInflater();
View row=inflater.inflate(ROW_TO_TEST, null);
return(row);
}
}
}
[/sourcecode]
That gave me the following visual result:
Since that seemed to line up with what the author was getting, I felt I had reproduced the problem, and set about getting it to work. This eventually took 13 different test layouts. Since this post would be a mile long if I documented each and every one of them, I’ll pick out the highlights.
First, I added background colors, so we could better see what widget is taking up what space on-screen:
[sourcecode lang=”xml”]
[/sourcecode]
While ugly, the colors do help to demonstrate what is what. The RelativeLayout
is brick red, the LinearLayout
is blue (of which only a hint can be seen), and the three TextView
s are green, mustard yellow,… and the third is not visible in the layout.
Eventually, I tried switching to a full box model, trying to figure out why the two stacked TextView
widgets were appearing on top of each other:
[sourcecode lang=”xml”]
Now, we see the first TextView
(“Upper”) in purple and no lower one.
Thinking that the problem might be one of layout weights, I added android:layout_weight=”1″ to each of the stacked TextView
widgets, which got me:
You see that they are now somewhat stacking, but their full height is not being properly utilized, so they are somewhat squashed.
On a whim, I commented out the “Left Center” TextView
, and got:
So now they’re stacking. This suggests that, somehow, the height of the layout was being dictated by the initial TextView
more than the stacked pair of TextView
widgets.
I then started trying to work this back into a RelativeLayout
overall parent, yielding:
[sourcecode lang=”xml”]
[/sourcecode]
Note the use of layout_centerHorizontal="true"
rather than layout_centerInParent="true"
. One would think they should be equivalent in a row whose height is being dictated by the to-be-centered widget. In practice, it appears layout_centerHorizontal
works better in this case. Needless to say, we now have our stacked TextView
widgets properly positioned.
So, we uncomment our “Left Center” TextView
and…
On the plus side, it did not foul up our Upper and Lower TextView
widgets. On the other hand, the Left Center TextView
is still misbehaving.
If we change the Left Center TextView
to use layout_alignParentBottom="true"
instead of layout_centerVertical="true"
, we see:
That should have the Left Center TextView
‘s bottom aligned with the parent’s bottom. Combine this with the previous result, and it would appear that the RelativeLayout
knows the proper height, but for some reason is translating the position upwards by 50%, which is fouling up the layout.
And at this point, I surrendered. This could be a bug. This could be the ways of RelativeLayout
being inscrutable.
If this were my application, I’d dump the RelativeLayout
and stick to a “box model”, using nested LinearLayout
s:
[sourcecode lang=”xml”]
Technically, this is not the same as the original. In the original, the author wanted the Upper/Lower TextView
pair to be centered across the row. In this implementation, they are centered across the part of the row not used by the Left Center TextView
. The difference is subtle to the naked eye, and it may be the replacement will suffice for the application’s business needs.