¿Cómo alineo las vistas en la parte inferior de la pantalla?

636

Aquí está mi código de diseño;

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

    <TextView android:text="@string/welcome"
        android:id="@+id/TextView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
    </TextView>

    <LinearLayout android:id="@+id/LinearLayout"
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="bottom">

            <EditText android:id="@+id/EditText"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content">
            </EditText>

            <Button android:text="@string/label_submit_button"
                android:id="@+id/Button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
            </Button>

    </LinearLayout>

</LinearLayout>

Esto se ve a la izquierda y lo que quiero que se vea es a la derecha.

Diseño de Android: real (izquierda) y deseado (derecha)

La respuesta obvia es establecer TextView en fill_parent en altura, pero esto no deja espacio para el botón o campo de entrada.

Esencialmente, el problema es que quiero que el botón Enviar y la entrada de texto tengan una altura fija en la parte inferior y que la vista de texto llene el resto del espacio. Del mismo modo, en el diseño lineal horizontal, quiero que el botón Enviar ajuste su contenido y que la entrada de texto llene el resto del espacio.

Si se le dice al primer elemento de un diseño lineal que complete_parent, hace exactamente eso, sin dejar espacio para otros elementos. ¿Cómo obtengo un elemento que está primero en un diseño lineal para llenar todo el espacio aparte del mínimo requerido por el resto de los elementos en el diseño?


Diseños relativos fueron de hecho la respuesta:

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

    <TextView
        android:text="@string/welcome"
        android:id="@+id/TextView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true">
    </TextView>

    <RelativeLayout
        android:id="@+id/InnerRelativeLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true" >

        <Button
            android:text="@string/label_submit_button"
            android:id="@+id/Button"
            android:layout_alignParentRight="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
        </Button>

        <EditText
            android:id="@+id/EditText"
            android:layout_width="fill_parent"
            android:layout_toLeftOf="@id/Button"
            android:layout_height="wrap_content">
        </EditText>

    </RelativeLayout>

</RelativeLayout>
gav
fuente
77
@oneself Paint;) Estoy usando una máscara en el emulador, aunque es cortesía de Tea Vui Huang teavuihuang.com/android
gav
14
+1 para publicar el diseño XML que lo resolvió. Me ayudó a descubrir qué le pasaba al mío.
Aullador

Respuestas:

527

La forma moderna de hacer esto es tener un RestraintLayout y restringir la parte inferior de la vista al fondo del RestraintLayout conapp:layout_constraintBottom_toBottomOf="parent"

El siguiente ejemplo crea un FloatingActionButton que se alineará con el final y la parte inferior de la pantalla.

<android.support.constraint.ConstraintLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_height="match_parent"
   android:layout_width="match_parent">

<android.support.design.widget.FloatingActionButton
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"

    app:layout_constraintBottom_toBottomOf="parent"

    app:layout_constraintEnd_toEndOf="parent" />

</android.support.constraint.ConstraintLayout>

Como referencia, mantendré mi vieja respuesta.

Antes de la introducción de ConstraintLayout, la respuesta era un diseño relativo .


Si tiene un diseño relativo que llena toda la pantalla, debería poder usarlo android:layout_alignParentBottompara mover el botón a la parte inferior de la pantalla.

Si sus vistas en la parte inferior no se muestran en un diseño relativo, entonces tal vez el diseño de arriba ocupe todo el espacio. En este caso, puede colocar la vista, que debe estar en la parte inferior, primero en su archivo de diseño y colocar el resto del diseño sobre las vistas con android:layout_above. Esto permite que la vista inferior ocupe todo el espacio que necesita, y el resto del diseño puede ocupar todo el resto de la pantalla.

Janusz
fuente
55
FYI: eso no funcionaría dentro de un ScrollView. Este es el problema que estoy enfrentando ahora. Ver stackoverflow.com/questions/3126347/…
IgorGanapolsky
66
Eso es correcto ScrollViews y diseños relativos no se mezclan muy bien. Si tiene mucho contenido para mostrar todo en una página, simplemente use una distribución lineal y colóquela en la vista inferior al final. Si desea que la vista aparezca en último lugar en la vista de desplazamiento en pantallas pequeñas y en la parte inferior de la página en teléfonos más grandes, considere usar diferentes archivos de diseño y use calificadores de recursos para permitir que el dispositivo elija el archivo de diseño correcto.
Janusz
ok ... ¿cuál es el punto del segundo párrafo de la respuesta aquí? "¿Debería encontrar primero un diseño que cubra la parte inferior de la pantalla"? entonces deberíamos usar layout_alignParentBottom dentro del diseño? ¿Para qué necesitamos android:layout_above?
eugene
Necesita lo anterior si desea algo como una barra en la parte inferior y luego un diseño lineal encima de esta barra que se extiende desde la parte superior de la pantalla hasta la barra.
Janusz
1
He leído en uno de "Android Weekly" that RelativeLayoutque consume memoria y debe evitarse siempre que sea posible.
Tomasz Mularczyk
153

En un caso, ScrollViewesto no funciona, ya RelativeLayoutque luego se superpondría con lo que esté en ScrollViewla parte inferior de la página.

Lo arreglé usando un estiramiento dinámico FrameLayout:

<ScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent" 
    android:layout_width="match_parent"
    android:fillViewport="true">
    <LinearLayout 
        android:id="@+id/LinearLayout01"
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical">

                <!-- content goes here -->

                <!-- stretching frame layout, using layout_weight -->
        <FrameLayout
            android:layout_width="match_parent" 
            android:layout_height="0dp"
            android:layout_weight="1">
        </FrameLayout>

                <!-- content fixated to the bottom of the screen -->
        <LinearLayout 
            android:layout_width="match_parent" 
            android:layout_height="wrap_content"
            android:orientation="horizontal">
                                   <!-- your bottom content -->
        </LinearLayout>
    </LinearLayout>
</ScrollView>
Bram Avontuur
fuente
1
esto es genial, además, es "mínimamente invasivo" y más intuitivo que el enfoque RelativeLayout. ¡Daría más de un voto a favor si pudiera!
2011
44
Uso su solución en mi aplicación, pero en mi caso quiero que cuando aparezca el teclado, los botones permanezcan en la parte inferior de la pantalla (detrás del teclado). ¿Hay alguna solución para eso? Thaks
Yoann
1
@DoubleYo: en el manifiesto android: windowSoftInputMode = "ajustarPan"
Kopfgeldjaeger
2
SI desea que la parte inferior se repare permanentemente para que se muestre todo el tiempo, esto no funciona. De lo contrario, funciona.
K - La toxicidad en SO está creciendo.
72

Puede mantener su diseño lineal inicial anidando el diseño relativo dentro del diseño lineal:

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

    <TextView android:text="welcome" 
        android:id="@+id/TextView" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content">
    </TextView>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <Button android:text="submit" 
            android:id="@+id/Button" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true">
        </Button>
        <EditText android:id="@+id/EditText" 
            android:layout_width="match_parent" 
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@id/Button"
            android:layout_alignParentBottom="true">
        </EditText>
    </RelativeLayout>
</LinearLayout>
pseudosudo
fuente
2
Este es un enfoque desordenado ya que no es muy modular. No deberías tener diseños superpuestos. Este diseño no funcionará tan pronto como desee cambiar el fondo de RelativeLayout o desee agrandar cualquiera de las vistas o agregar vistas.
Patrick
42

La respuesta anterior (por Janusz) es bastante correcta, pero personalmente no me siento 100% cómodo con RelativeLayouts, por lo que prefiero presentar un 'relleno', TextView vacío, como este:

<!-- filler -->
<TextView android:layout_height="0dip" 
          android:layout_width="fill_parent"
          android:layout_weight="1" />

antes del elemento que debería estar en la parte inferior de la pantalla.

Timores
fuente
¿Esto se expandirá al eje x o y? ¿Dar 0dip para altura hará que la vista de texto no tenga altura? o se expandirá tanto como pueda al eje x?
Lukap
Esto se expande verticalmente porque la altura (eje vertical) se establece en 0 y el peso en 1 (suponiendo que otros elementos tengan un peso cero).
Timores
En el eje x, será como su padre (fill_parent)
Timores
En lugar de una vista de texto, usaría otro diseño lineal. La vista de diseño parece implicar que se puede usar para llenar el espacio.
Venir
33

También puede hacer esto con LinearLayout o ScrollView. A veces es más fácil de implementar que un RelativeLayout. Lo único que debe hacer es agregar la siguiente vista antes de las Vistas que desea alinear en la parte inferior de la pantalla:

<View
    android:layout_width="wrap_content"
    android:layout_height="0dp"
    android:layout_weight="1" />

Esto crea una vista vacía, llena el espacio vacío y empuja las siguientes vistas a la parte inferior de la pantalla.

keybee
fuente
27

Esto tambien funciona.

<LinearLayout 
    android:id="@+id/linearLayout4"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_below="@+id/linearLayout3"
    android:layout_centerHorizontal="true"
    android:orientation="horizontal" 
    android:gravity="bottom"
    android:layout_alignParentBottom="true"
    android:layout_marginTop="20dp"
>

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" 

    />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" 


    />

</LinearLayout>

gravity = "bottom" para flotar elementos LinearLayout en el fondo

Michael Reed
fuente
12
android: layout_alignParentBottom = "true" no tiene ningún efecto a menos que LinearLayout esté anidado dentro de un RelativeLayout.
Thomas Dignan
Una explicación estaría en orden (por ejemplo, el cambio esencial, cómo funciona, por qué funciona, etc.).
Peter Mortensen
26

1. Úselo ConstraintLayouten su diseño raíz

Y configurar app:layout_constraintBottom_toBottomOf="parent"para dejar el diseño en la parte inferior de la pantalla:

<LinearLayout
    android:id="@+id/LinearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintBottom_toBottomOf="parent">
</LinearLayout>

2. Úselo FrameLayouten su diseño raíz

Solo configura android:layout_gravity="bottom"tu diseño

<LinearLayout
    android:id="@+id/LinearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:orientation="horizontal">
</LinearLayout>

3. Úselo LinearLayouten su diseño raíz ( android:orientation="vertical")

(1) Establecer un diseño android:layout_weight="1"en la parte superior de su diseño

<TextView
    android:id="@+id/TextView"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:text="welcome" />

(2) Establecer el niño LinearLayoutparaandroid:layout_width="match_parent" android:layout_height="match_parent" android:gravity="bottom"

El atributo principal es ndroid:gravity="bottom", dejar que el niño vea en la parte inferior del diseño.

<LinearLayout
    android:id="@+id/LinearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="bottom"
    android:orientation="horizontal">
</LinearLayout>

4. Uso RelativeLayouten el diseño raíz

Y configurar android:layout_alignParentBottom="true"para dejar que el diseño en la parte inferior de la pantalla

<LinearLayout
    android:id="@+id/LinearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:orientation="horizontal">
</LinearLayout>

Salida

Ingrese la descripción de la imagen aquí

KeLiuyue
fuente
20

Siguiendo la elegante solución de Timores , he descubierto que lo siguiente crea un relleno vertical en un LinearLayout vertical y un relleno horizontal en un LinearLayout horizontal:

<Space
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1" />
stevehs17
fuente
@sepehr Debe haber otro factor en juego en el caso de que encuentre que mi solución no funciona. Acabo de probar mi solución en un diseño de fragmento, y funciona allí también.
stevehs17
los pesos se admiten en diseños lineales y @sepehr también funcionarán en fragmentos, actividades, notificaciones, diálogos;)
Jan Rabe
16

Ni siquiera necesita anidar el segundo relativediseño dentro del primero. Simplemente use el android:layout_alignParentBottom="true"en el Botón y EditText .

Steve Haley
fuente
Solo una nota de que aunque esto funciona con Button y EditText, si intentara alinear un TableLayout de esta manera, no funcionaría. Tendría que anidarlo dentro de otro RelativeLayout.
11

Si no desea hacer muchos cambios, simplemente podría poner:

android:layout_weight="1"

para el TextView que tiene ID como @+id/TextViewie

<TextView android:text="@string/welcome" 
    android:id="@+id/TextView" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"
    android:layout_weight="1">
</TextView>
Kiran Parmar
fuente
O agregue un LinearLayout circundante con android: layout_weight = "1" - ¡esto también funciona bien dentro de un ScrollView!
bk138
7

Creando encabezado y pie de página , aquí hay un ejemplo:

XML de diseño

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/backgroundcolor"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="40dp"
        android:background="#FF0000">
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="40dp"
        android:layout_alignParentBottom="true"
        android:background="#FFFF00">
    </RelativeLayout>

</RelativeLayout>

Captura de pantalla

Ingrese la descripción de la imagen aquí

Madan Sapkota
fuente
4

Usa el siguiente código. Alinee el botón con el botón. Esta funcionando.

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

    <Button
        android:id="@+id/btn_back"
        android:layout_width="100dp"
        android:layout_height="80dp"
        android:text="Back" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.97"
        android:gravity="center"
        android:text="Payment Page" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"/>

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

</LinearLayout>
sharma_kunal
fuente
3

Para un caso como este, use siempre RelativeLayouts. Un LinearLayout no está diseñado para tal uso.

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

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

        <!-- Place your layout here -->

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_gravity="bottom"
        android:orientation="horizontal"
        android:paddingLeft="20dp"
        android:paddingRight="20dp" >

        <Button
            android:id="@+id/setup_macroSavebtn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Save" />

        <Button
            android:id="@+id/setup_macroCancelbtn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Cancel" />

        </LinearLayout>

</RelativeLayout>
Shubham A.
fuente
2

Uso android:layout_alignParentBottom="true" en tu <RelativeLayout>.

Esto definitivamente ayudará.

jigar
fuente
1
Eso supone que el usuario quiere usar un RelativeLayout.
IgorGanapolsky
2

En caso de que tenga una jerarquía como esta:

<ScrollView> 
  |-- <RelativeLayout> 
    |-- <LinearLayout>

Primero, aplique android:fillViewport="true"al ScrollViewy luego aplique android:layout_alignParentBottom="true"al LinearLayout.

Esto funcionó para mí perfectamente.

<ScrollView
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:scrollbars="none"
    android:fillViewport="true">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:id="@+id/linearLayoutHorizontal"
            android:layout_alignParentBottom="true">
        </LinearLayout>
    </RelativeLayout>
</ScrollView>
Príncipe
fuente
2

Usted sólo puede dar a su vista superior del niño (el TextView @ + / Identificación del TextView ) un atributo: android:layout_weight="1".

Esto forzará a todos los demás elementos debajo de él hacia abajo.

IgorGanapolsky
fuente
2

Esto también se puede hacer con un diseño lineal.

Solo proporcione Altura = 0dp y peso = 1 al diseño anterior y al que desea en la parte inferior. Simplemente escriba altura = contenido envolvente y sin peso.

Proporciona contenido de ajuste para el diseño (el que contiene su texto y botón de edición) y luego el que tiene peso ocupa el resto del diseño.

Descubrí esto por accidente.

raihan ahmed
fuente
0

Usé la solución que Janusz publicó, pero agregué relleno a la última Vista ya que la parte superior de mi diseño era una Vista de desplazamiento.

ScrollView estará parcialmente oculto a medida que crece con el contenido. El uso android:paddingBottomen la última Vista ayuda a mostrar todo el contenido en la Vista de desplazamiento.

jeremyvillalobos
fuente