views:

121

answers:

3

Sorry for the extremely bad title, I have no other idea what to call this question. What I'm trying to do is this: have a RelativeLayout which has two children:

  1. one with layout_centerInParent="true"
  2. one with layout_alignParentBottom="true"

However, when the device is in landscape mode, element (1) appears slightly over or under element (2). But, element (1) has enough space above it to appear above element (2). How could I make the layout so that if the screen is too small to center element (1) and make both elements not overlap, then align element (1) above (as in layout_above) element (2)?

+1  A: 

Alright here's a leftfield suggestion that might work if your element (1) isn't too resource intensive.

Have two versions of element (1), the first with layout_centerInParent="true" and the second with layout_above="@id\element2". Default them both to android:visibility="invisible". In your onCreate Post a Runnable that inspects the Y dimension of both elements, and sets View.VISIBLE on the element with the smallest value.

Jim Blackler
For this solution I'd have to use `.postDelayed()` (`.post()` doesn't work), which seems very ugly to me. Still, +1 for the idea.
Felix
+1  A: 

New idea:

This is another idea that's sort of a workaround in that it's not very elegant, but it's very simple. Put element (1) in its own < LinearLayout > configured like so:

<LinearLayout android:layout_width="fill_parent"
    android:layout_height="fill_parent" // More on this line below
    android:layout_alignParentTop="true"
    android:layout_above="@id/element2"
    android:gravity="center">

That linear layout will always span from the top of screen to just above element (2), and since its gravity is "center", element (1) will always be in the middle of whatever space is available for it. Note: The line android:layout_height="..." is required, but doesn't seem to actually do anything. Whether it's fill_parent or wrap_content, its height is overridden by the lines anchoring its top to the ParentTop and its bottom to element(2). However, not having the line makes it crash with a Runtime exception.


Original, not very good idea:

Another less-than-ideal solution is to use two layout files. Put the portrait layout xml in your layout folder and the landscape layout in a new folder called layout-land. Android then automatically selects the right one based on the orientation of the phone. I think you could use layout-port, but putting the portrait one in just layout makes sure it knows which one to use by default.

Steve H
Nice idea, but even if the device is in landscape mode it might have enough space to fit element (1) in the center. And if it's a really big device it might actually look awkward.
Felix
I've edited my answer to give another suggestion.
Steve H
Thanks for the new idea, will try it a bit later
Felix
+1  A: 

This should work to give you a layout where the text1 item fills the available space above text2, and is centered vertically and horizontally in that space; and text2 is on the bottom, centered horizontally.

<LinearLayout 
    android:orientation="vertical"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent">

    <TextView
        android:id="@android:id/text1" 
        android:layout_width="fill_parent" 
        android:layout_height="0dp" 
        android:layout_weight="1" 
        android:text="Centered" 
        android:gravity="center_vertical|center_horizontal"
        />

    <TextView
        android:id="@android:id/text2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Bottom"
        android:gravity="center_horizontal"
        />
</LinearLayout>

The important parts are android:layout_weight, combined with android:gravity.

Joe
That's what I finally went with. Changed the `RelativeLayout` to a `LinearLayout` and used the weight/gravity combo you suggested. Thanks.
Felix