views:

780

answers:

1

Hi, I recently struggled with an apparently simple Android layout: I wanted a WebView above a Button. It worked fine with the following parameters:

WebView:
  Height: wrap-content
  Weight: unset (by the way, what is the default?)

Button:
  Height: wrap-content
  Weight: unset

However if the web page became too big it spilled out over the button. I tried various combinations of weights and heights, and all except one either completely hide the button, or partially cover it. This is the one that works (copied from http://code.google.com/p/apps-for-android/source/browse/trunk/Samples/WebViewDemo/res/layout/main.xml):

WebView:
  Height: 0
  Weight: 1

Button:
  Height: wrap-content
  Weight: unset

If you change any of those, e.g. give button a weight or change the WebView height to wrap-content then it doesn't work. My question is: Why? Can someone please explain what on Earth the android layout system is thinking?

A: 

Something like the following should give you what you want. The key is the layout_height="fill_parent" and layout_weight="1" for the WebView.

<LinearLayout android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
        <WebView android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1" />

        <Button android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
</LinearLayout>  


Edit: Whoops, I misunderstood your question. It's the layout_weight that makes it not spill over the button (or textview in your example). I'm not sure why it happens, but if there's one "fill_parent" item in your LinearLayout, in addition to one or more "wrap_content" items, you need to specify a layout_weight for the "fill_parent" item, or it'll take over the space for the rest of the widgets.

synic
`fill_parent` will take up all remaining space in a `LinearLayout`, so you cannot have widgets after it. On the whole, for layouts like this, I recommend a `RelativeLayout`, as the rules are more explicit and therefore easier to maintain (you don't have to remember magic `layout_weight` tricks). Just have the `Button` be `alignParentBottom` and have the `WebView` be `alignParentTop and above the `Button`.
CommonsWare
What about cases where you have 4 or 5 widgets, the first two are "wrap_content", the third is "fill_parent", and the last two are "Wrap_content". This would be a pain to maintain with a RelativeLayout - especially if you add another widget between two of the other widgets. With a LinearLayout, you already have to remember to give the one "growable" widget "fill_parent". You just have to remember to also give it the "layout_weight" "trick".
synic
`RelativeLayout` won't be difficult for that case either. The top widget would be `alignParentTop`, second would `layout_below` the first and the bottom two would be done similarly but aligned to the bottom. The middle "growable" widget would just have to `layout_below` the lower widget in the top group and `layout_above` the widget in the bottom group.
jqpubliq
Thanks for the responses, but I still don't understand why you have to have height: 0. I guess I'll have to look at the source!
Timmmm