Comment aligner les vues en bas de l'écran?

636

Voici mon code de mise en page;

<?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>

À quoi cela ressemble est à gauche et à quoi je veux ressembler est à droite.

Disposition Android - réelle (gauche) et souhaitée (droite)

La réponse évidente consiste à définir TextView sur fill_parent sur la hauteur, mais cela ne laisse aucune place au bouton ou au champ de saisie.

Essentiellement, le problème est que je veux que le bouton de soumission et l'entrée de texte soient à une hauteur fixe en bas et que la vue de texte remplisse le reste de l'espace. De même, dans la disposition linéaire horizontale, je veux que le bouton Soumettre enveloppe son contenu et que l'entrée de texte remplisse le reste de l'espace.

Si le premier élément d'une disposition linéaire est dit à fill_parent, il fait exactement cela, ne laissant aucune place aux autres éléments. Comment puis-je obtenir un élément qui est le premier dans une mise en page linéaire pour remplir tout l'espace en dehors du minimum requis par le reste des éléments de la mise en page?


Les dispositions relatives étaient en effet la réponse:

    <?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
la source
7
@oneself Paint;) J'utilise un skin sur l'émulateur mais avec l'aimable autorisation de Tea Vui Huang teavuihuang.com/android
gav
14
+1 pour avoir publié la mise en page XML qui l'a résolu. M'a aidé à comprendre ce qui n'allait pas avec le mien.
Howler

Réponses:

527

La manière moderne de procéder consiste à avoir un ConstraintLayout et à contraindre le bas de la vue au bas du ConstraintLayout avecapp:layout_constraintBottom_toBottomOf="parent"

L'exemple ci-dessous crée un FloatingActionButton qui sera aligné à la fin et au bas de l'écran.

<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>

Pour référence, je garderai mon ancienne réponse.

Avant l'introduction de ConstraintLayout, la réponse était une disposition relative .


Si vous avez une disposition relative qui remplit tout l'écran, vous devriez pouvoir utiliser android:layout_alignParentBottompour déplacer le bouton en bas de l'écran.

Si vos vues en bas ne sont pas affichées dans une disposition relative, alors la disposition ci-dessus peut prendre tout l'espace. Dans ce cas, vous pouvez placer la vue, qui devrait être en bas, d'abord dans votre fichier de mise en page et positionner le reste de la mise en page au-dessus des vues avec android:layout_above. Cela permet à la vue de dessous de prendre autant d'espace qu'elle en a besoin et le reste de la mise en page peut remplir tout le reste de l'écran.

Janusz
la source
5
FYI: cela ne fonctionnerait pas dans un ScrollView. C'est le problème auquel je suis confronté maintenant. Voir stackoverflow.com/questions/3126347/…
IgorGanapolsky
6
C'est-à-dire que les ScrollViews corrects et les dispositions relatives ne se mélangent pas très bien. Si vous avez trop de contenu pour tout afficher sur une seule page, utilisez simplement une disposition linéaire et placez la vue de dessous en dernier. Si vous souhaitez que la vue apparaisse en dernier dans la vue de défilement sur les petits écrans et au bas de la page sur les téléphones plus gros, envisagez d'utiliser des fichiers de mise en page différents et utilisez des qualificateurs de ressources pour laisser l'appareil choisir le fichier de mise en page correct.
Janusz
ok .. quel est le point du deuxième paragraphe de la réponse ici? "Vous devriez d'abord trouver une disposition qui couvre le bas de l'écran"? alors nous devrions utiliser layout_alignParentBottom à l'intérieur de la mise en page? De quoi avons-nous besoin android:layout_above?
eugene
Vous avez besoin de ce qui précède si vous voulez quelque chose comme une barre en bas, puis un LinearLayout au-dessus de cette barre qui s'étend du haut de l'écran à la barre.
Janusz
1
J'ai lu dans l'un des "Android Weekly" that RelativeLayoutconsomme beaucoup de mémoire et doit être évité autant que possible.
Tomasz Mularczyk
153

Dans un ScrollViewcela ne fonctionne pas, car le RelativeLayoutchevaucherait alors tout ce qui se trouve en ScrollViewbas de la page.

Je l'ai corrigé en utilisant un étirement dynamique 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
la source
1
c'est génial - aussi, c'est "minimal invasif", et plus intuitif que l'approche RelativeLayout. Je donnerais plus d'un vote positif si je le pouvais!
manmal
4
J'utilise votre solution dans mon application, mais dans mon cas, je veux que lorsque le clavier apparaît, les boutons restent en bas de l'écran (derrière le clavier) Il y a une sulution pour ça? Merci.
Yoann
1
@DoubleYo: dans le manifeste android: windowSoftInputMode = "adjustPan"
Kopfgeldjaeger
2
SI vous voulez que le fond soit fixé de façon permanente, de sorte qu'il s'affiche tout le temps, cela ne fonctionne pas. Sinon ça marche.
K - La toxicité du SO augmente.
72

Vous pouvez conserver votre disposition linéaire initiale en imbriquant la disposition relative dans la disposition linéaire:

<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
la source
2
Il s'agit d'une approche désordonnée en ce qu'elle n'est pas très modulaire. Vous ne devriez pas avoir de mises en page qui se chevauchent. Cette conception ne fonctionnera pas dès que vous souhaitez modifier l'arrière-plan du RelativeLayout ou que vous souhaitez agrandir l'une des vues ou ajouter des vues.
Patrick
42

La réponse ci-dessus (par Janusz) est tout à fait correcte, mais personnellement je ne me sens pas à 100% à l'aise avec RelativeLayouts, donc je préfère introduire un 'filler', TextView vide, comme ceci:

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

devant l'élément qui devrait être en bas de l'écran.

Timores
la source
Est-ce que ça va se développer sur l'axe x ou y. Donner 0dip pour la hauteur rendra le texte sans aucune hauteur? ou va s'étendre autant qu'il le peut sur l'axe x?
Lukap
Cela se développe verticalement car la hauteur (axe vertical) est définie sur 0 et le poids sur 1 (en supposant que d'autres éléments ont un poids nul).
Timores
Sur l'axe des x, ce sera comme son parent (fill_parent)
Timores
Plutôt qu'une vue texte, j'utiliserais une autre disposition linéaire. La mise en page semble impliquer qu'elle peut être utilisée pour remplir l'espace?
ComeIn
33

Vous pouvez également le faire avec un LinearLayout ou un ScrollView. Parfois, il est plus facile à implémenter qu'un RelativeLayout. La seule chose que vous devez faire est d'ajouter la vue suivante avant les vues que vous souhaitez aligner en bas de l'écran:

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

Cela crée une vue vide, remplissant l'espace vide et poussant les vues suivantes vers le bas de l'écran.

keybee
la source
27

Cela fonctionne également.

<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" pour faire flotter les éléments LinearLayout vers le bas

Michael Reed
la source
12
android: layout_alignParentBottom = "true" n'a aucun effet sauf si le LinearLayout est imbriqué dans un RelativeLayout.
Thomas Dignan
Une explication serait en règle (par exemple, le changement essentiel, comment il fonctionne, pourquoi il fonctionne, etc.).
Peter Mortensen
26

1. Utilisez ConstraintLayoutdans votre disposition racine

Et paramétrez app:layout_constraintBottom_toBottomOf="parent"pour laisser la mise en page en bas de l'écran:

<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. Utilisation FrameLayout dans votre disposition racine

Définissez simplement android:layout_gravity="bottom"votre mise en page

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

3. Utilisez LinearLayoutdans votre disposition racine (android:orientation="vertical" )

(1) Définissez une mise android:layout_weight="1"en page en haut de votre mise en page

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

(2) Réglez l'enfant LinearLayoutpourandroid:layout_width="match_parent" android:layout_height="match_parent" android:gravity="bottom"

L'attribut principal est ndroid:gravity="bottom", laissez la vue enfant au bas de la mise en page.

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

4. Utilisation RelativeLayoutdans la disposition racine

Et réglé android:layout_alignParentBottom="true"pour laisser la mise en page en bas de l'écran

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

Production

Entrez la description de l'image ici

KeLiuyue
la source
20

Faisant suite à la solution élégante Timores , j'ai constaté que ce qui suit crée un remplissage vertical dans un LinearLayout vertical et un remplissage horizontal dans un LinearLayout horizontal:

<Space
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1" />
stevehs17
la source
@sepehr Il doit y avoir un autre facteur en jeu dans le cas où vous avez trouvé où ma solution ne fonctionne pas. Je viens d'essayer ma solution dans une mise en page fragmentée, et cela fonctionne également là-bas.
stevehs17
les poids sont pris en charge dans les dispositions linéaires et @sepehr, ils fonctionneront également dans des fragments, des activités, des notifications, des dialogues;)
Jan Rabe
16

Vous n'avez même pas besoin d'imbriquer la deuxième relativedisposition à l'intérieur de la première. Utilisez simplement le android:layout_alignParentBottom="true"dans le bouton et EditText .

Steve Haley
la source
Juste une note que bien que cela fonctionne avec le Button et EditText, si vous essayez d'aligner un TableLayout de cette façon, cela ne fonctionnera pas. Vous devez l'imbriquer à l'intérieur d'un autre RelativeLayout.
11

Si vous ne souhaitez pas apporter de nombreuses modifications, vous pouvez simplement mettre:

android:layout_weight="1"

pour le TextView ayant l'ID comme @+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
la source
Ou ajoutez un LinearLayout environnant avec android: layout_weight = "1" - cela fonctionne aussi bien dans un ScrollView!
bk138
7

En créant à la fois l'en- tête et le pied de page , voici un exemple:

Disposition XML

<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>

Capture d'écran

Entrez la description de l'image ici

Madan Sapkota
la source
4

Utilisez le code ci-dessous. Alignez le bouton sur le bouton. Ça marche.

<?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
la source
3

Pour un cas comme celui-ci, utilisez toujours RelativeLayouts. Un LinearLayout n'est pas destiné à une telle utilisation.

<?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.
la source
2

Utilisez android:layout_alignParentBottom="true" dans votre<RelativeLayout> .

Cela vous aidera certainement.

jigar
la source
1
Cela suppose que l'utilisateur souhaite utiliser un RelativeLayout.
IgorGanapolsky
2

Si vous avez une hiérarchie comme celle-ci:

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

Tout d'abord, appliquez-vous android:fillViewport="true"à ScrollViewpuis appliquez-vous android:layout_alignParentBottom="true"à LinearLayout.

Cela a parfaitement fonctionné pour moi.

<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>
Prince
la source
2

Vous pouvez simplement donner à votre vue enfant supérieure (TextView @ + id / TextView ) un attribut: android:layout_weight="1" .

Cela forcera tous les autres éléments en dessous vers le bas.

IgorGanapolsky
la source
2

Cela peut également être fait avec une disposition linéaire.

Indiquez simplement Height = 0dp et weight = 1 à la disposition ci-dessus et à celle que vous souhaitez en bas. Écrivez simplement hauteur = contenu enveloppé et sans poids.

Il fournit un contenu d'habillage pour la mise en page (celui qui contient votre texte et bouton d'édition), puis celui qui a du poids occupe le reste de la mise en page.

Je l'ai découvert par accident.

raihan ahmed
la source
0

J'ai utilisé la solution publiée par Janusz, mais j'ai ajouté un remplissage à la dernière vue, car la partie supérieure de ma mise en page était un ScrollView.

Le ScrollView sera partiellement masqué à mesure qu'il grandit avec le contenu. L'utilisation android:paddingBottomde la dernière vue permet d'afficher tout le contenu du ScrollView.

jeremyvillalobos
la source