16

The layout I try to implement is (I think) pretty simple.

One TextView expands depending on what is inside. Just below are two buttons (OK/Cancel).

I can make the buttons stick to the bottom of the screen and that works fine. But I would like to have those buttons just below the TextView. I have tried a lot of different things, but here is my latest layout :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
        >
    <ScrollView android:id="@+id/Scroll"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
            >
        <TextView
                android:id="@+id/Text"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                />
    </ScrollView>
    <RelativeLayout android:id="@+id/buttons"
                    android:layout_height="fill_parent"
                    android:layout_width="fill_parent"
                    android:layout_below="@+id/Scroll"
                    android:layout_above="@+id/bottom"
            >
        <LinearLayout
                android:orientation="horizontal"
                android:layout_height="wrap_content"
                android:layout_width="fill_parent">
            <Button android:id="@+id/ButtonOK"
                    android:layout_height="80dp"
                    android:layout_width="fill_parent"
                    android:text="OK"
                    android:layout_weight="1"/>
            <Button android:id="@+id/ButtonCancel"
                    android:layout_height="80dp"
                    android:layout_width="fill_parent"
                    android:text="Cancel"
                    android:layout_weight="1"/>
        </LinearLayout>
    </RelativeLayout>
    <LinearLayout android:id="@+id/bottom"
                  android:layout_height="0px"
                  android:layout_width="fill_parent"
                  android:layout_alignParentBottom="true"/>
</RelativeLayout>

The empty linearlayout at the end is an (unsuccessful) attempt to prevent the view to extend past the bottom of the screen...

In everything I tried, either the buttons are at the bottom of the screen or they would go past it when the TextView is too big.

Here is a sketch of what I am trying to do :enter image description here

Matthieu
  • 16,103
  • 10
  • 59
  • 86

5 Answers5

26

Is the goal just to have a scrollable area that takes up the entire page minus the amount taken up by some buttons at the bottom?

If that's the case, you can use a LinearLayout at the outer level and make use of weights:

<LinearLayout 
   android:layout_height="wrap_content" 
   orientation="vertical"...>
   <ScrollView
      android:layout_height="0dp"
      android:layout_weight="1"
      .../>
   <LayoutWithButtons
      android:layout_height="wrap_content"
      ..../>
</LinearLayout>
Silver Dragon
  • 5,480
  • 6
  • 41
  • 73
Cheryl Simon
  • 46,552
  • 15
  • 93
  • 82
  • 1
    Hmm, what happens if you set the outer LinearLayout to wrap_content? If that doesn't work on its own, wrap it in another LinearLayout with a greedy (height=0, weight=1) invisible element below it? – Cheryl Simon May 19 '11 at 23:15
  • The scroll view does? In which case? – Cheryl Simon May 19 '11 at 23:24
  • 1
    Setting the outer Layout with wrap_content worked. If I add the other greedy invisible Layout, the buttons would be stuck in the middle of the screen. But you got it.. thanks ! – Matthieu May 19 '11 at 23:42
  • 1
    I'm getting an error that `layout_height="0"` is not a valid value, but using `wrap_content` seems to work perfectly. – Mark Whitaker Nov 28 '11 at 11:25
1

I found this link that really helped me.

http://www.droidnova.com/layout-technique-static-elements-below-scrollview,123.html

I have some very specific customized needs for a keyboard solution -- requiring me to handle the display and tear-down of the keyboard on my own as a z-layer element in a frameLayout. I use the solution in that link to accomplish that and change the size of the scrollView at the same time. The buttons in the scroll view move from flush with the bottom of the screen to flush with the top of the keyboard.

The key is having android:fillViewport="true" on the scrollView. Then programmatically setting the bottom margin of the scrollView to and the top margin of the bottom element to -height.

Here's my two methods that handle it:

private void setMargins_noKeyboard()
{
    ScrollView fieldsScroller = (ScrollView)findViewById(R.id.scroll_fields_view);
    FrameLayout keyboardFrame = (FrameLayout)findViewById(R.id.keyboard_root);
    int buttonsKeyboardSize = keyboardFrame.getHeight();

    MarginLayoutParams frameParams = (MarginLayoutParams)keyboardFrame.getLayoutParams();
    frameParams.setMargins(0, 0, 0, 0);

    MarginLayoutParams scrollParams = (MarginLayoutParams)fieldsScroller.getLayoutParams();
    scrollParams.setMargins(0, 0, 0, 0);

    keyboardFrame.setLayoutParams(frameParams);
    fieldsScroller.setLayoutParams(scrollParams);
}

private void setMargins_keyboard()
{
    ScrollView fieldsScroller = (ScrollView)findViewById(R.id.scroll_fields_view);
    FrameLayout keyboardFrame = (FrameLayout)findViewById(R.id.keyboard_root);
    int buttonsKeyboardSize = keyboardFrame.getHeight();

    MarginLayoutParams frameParams = (MarginLayoutParams)keyboardFrame.getLayoutParams();
    frameParams.setMargins(0, -buttonsKeyboardSize, 0, 0);

    MarginLayoutParams scrollParams = (MarginLayoutParams)fieldsScroller.getLayoutParams();
    scrollParams.setMargins(0, 0, 0, buttonsKeyboardSize);

    keyboardFrame.setLayoutParams(frameParams);
    fieldsScroller.setLayoutParams(scrollParams);
}
alphonzo79
  • 938
  • 11
  • 12
  • After working with this quite a bit more, I have found that while the above answer works there is a better solution. Using a relative layout works very reliably without all the programatic gyrations of this answer. The key is at least one element that aligns with parent top and one element that aligns with parent bottom. The rest of the elements align relative to these two, the scrollview ultimately is sandwiched between anything that needs to remain stationary. – alphonzo79 Aug 13 '12 at 16:19
1

This should be the answer in xml

android:fillViewport="true"

http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/

a54studio
  • 965
  • 11
  • 11
  • IN the first case (when there is not many items in the list), then the scrollview would fill the whole screen which is NOT what I want... – Matthieu Mar 26 '12 at 02:15
0

This xml is ok for my app:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

     <TextView
        android:id="@+id/nameOfrecipe"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10sp"
        android:layout_marginLeft="10sp"
        android:layout_alignParentTop="true"
        android:textSize="20sp"
        android:text="Name of ingredients" />   

    <TableLayout
        android:id="@+id/tableOfingredients"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/nameOfrecipe"
        android:layout_marginTop="40sp"
        android:layout_marginLeft="10sp"
        android:layout_marginRight="10sp" >
    </TableLayout>
    <RelativeLayout android:id="@+id/l"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_below="@id/tableOfingredients"
        >                     
    <Button
        android:id="@+id/addDirectionsB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_alignParentBottom="true"     
        android:text="Add..." />

    <Button
        android:id="@+id/cancelDirectionsB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"   
        android:layout_toRightOf="@id/addDirectionsB"
        android:text="Cancel" />

       <ScrollView 
        android:id="@+id/directionsScroll"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_above="@id/addDirectionsB">        
            <EditText 
                android:id="@+id/directionsET"       
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:inputType="textMultiLine" >
                <requestFocus />
            </EditText>
    </ScrollView>
    </RelativeLayout>   
</RelativeLayout>
guest
  • 1
0
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
    >
    <RelativeLayout android:id="@+id/buttons"
                android:layout_height="wrap_content"
                android:layout_width="fill_parent"
                android:layout_alignParentBottom="true"
        >
    <LinearLayout
            android:orientation="horizontal"
            android:layout_alignParentTop="true"
            android:layout_height="wrap_content"
            android:layout_width="fill_parent">
        <Button android:id="@+id/ButtonOK"
                android:layout_height="80dp"
                android:layout_width="fill_parent"
                android:text="OK"
                android:layout_weight="1"/>
        <Button android:id="@+id/ButtonCancel"
                android:layout_height="80dp"
                android:layout_width="fill_parent"
                android:text="Cancel"
                android:layout_weight="1"/>
    </LinearLayout>
</RelativeLayout>
<ScrollView android:id="@+id/ScrollParent"
            android:layout_above="@id/buttons"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
        >

<ScrollView android:id="@+id/Scroll"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_alignParentTop="true"
        >
    <TextView
            android:id="@+id/Text"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            />
</ScrollView>
</RelativeLayout>

Hope it helps

Houcine
  • 24,001
  • 13
  • 56
  • 83
  • Same as for Mayra, I guess my description was not good enough. I added a sketch to make it more explicit. I want the buttons to be at the bottom only when the textfield is big enough... – Matthieu May 19 '11 at 22:46
  • and if the textView is so Big ??? your buttons will desapears , use a ScrollView as a parent of all your Layout,and then you will be sure that ur butons are below the textView, is that what u want ? One more thing, if your textView is getting bigger and bigger ,this push the buttons to the bottom again and again , so what is the reason of the scrollView ??? – Houcine May 19 '11 at 22:48
  • I want the buttons to always be visible, either just below the textfield when there is not much text, or at the bottom of the screen when the textfield use all the remaining space. The scrollview may not be needed if the textfield is scrollable, but the idea is to scroll through the text when needed. – Matthieu May 19 '11 at 22:53
  • i think that will be possible to do that programmatically , in the code , you will test , if the height of the Text is greater than (screen heigth - parentOfButtonHeigth) , than fixe the heigth of the scroll in order to not let the textView push the buttons at the bottom , – Houcine May 19 '11 at 23:16
  • 1
    what u can do in the Xml is limited, you can just fix the Button at the bottom of your layout , and then , if the textView is getting bigger and bigger , it will be scrollable , so , try the solution of Code :) – Houcine May 19 '11 at 23:50