Come allineare le viste nella parte inferiore dello schermo?


636

Ecco il mio codice di layout;

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

Quello che sembra è a sinistra e quello che voglio che sia è a destra.

Layout Android: reale (a sinistra) e desiderato (a destra)

La risposta ovvia è impostare TextView su fill_parent in altezza, ma ciò non lascia spazio per il pulsante o il campo di immissione.

In sostanza, il problema è che voglio che il pulsante di invio e la voce di testo abbiano un'altezza fissa nella parte inferiore e la vista del testo riempia il resto dello spazio. Allo stesso modo, nel layout lineare orizzontale voglio che il pulsante di invio ne racchiuda il contenuto e che l'inserimento di testo riempia il resto dello spazio.

Se viene detto al primo elemento in un layout lineare di fill_parent, lo fa esattamente, senza lasciare spazio per altri elementi. Come faccio a ottenere un elemento che è il primo in un layout lineare per riempire tutto lo spazio a parte il minimo richiesto dal resto degli articoli nel layout?


I layout relativi erano davvero la risposta:

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

7
@oneself Paint;) Sto usando una skin sull'emulatore anche se per gentile concessione di Tea Vui Huang teavuihuang.com/android
gav

14
+1 per la pubblicazione del layout XML che lo ha risolto. Mi ha aiutato a capire cosa c'era di sbagliato nel mio.
Howler,

Risposte:


527

Il modo moderno per eseguire questa operazione consiste nell'avere un vincolo di vincolo e vincolare il fondo della vista al fondo del vincolo di vincolo conapp:layout_constraintBottom_toBottomOf="parent"

L'esempio seguente crea un FloatingActionButton che verrà allineato all'estremità e alla parte inferiore dello schermo.

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

Per riferimento, terrò la mia vecchia risposta.

Prima dell'introduzione di ConstraintLayout la risposta era un layout relativo .


Se disponi di un layout relativo che riempie l'intero schermo, dovresti essere in grado di utilizzare android:layout_alignParentBottomper spostare il pulsante nella parte inferiore dello schermo.

Se le tue viste in basso non sono mostrate in un layout relativo, forse il layout sopra occupa tutto lo spazio. In questo caso puoi mettere la vista, che dovrebbe essere in fondo, prima nel tuo file di layout e posizionare il resto del layout sopra le viste con android:layout_above. Ciò consente alla vista inferiore di occupare tutto lo spazio necessario e il resto del layout può riempire tutto il resto dello schermo.


5
Cordiali saluti: che non funzionerebbe all'interno di ScrollView. Questo è il problema che sto affrontando ora. Vedere stackoverflow.com/questions/3126347/...
IgorGanapolsky

6
Questo è corretto ScrollView e layout relativi non si mescolano molto bene. Se devi visualizzare molti contenuti per visualizzare tutto su una sola pagina, usa un linearlayout e inserisci l'ultima vista in basso. Se si desidera che la vista appaia per ultima nella vista di scorrimento su piccoli schermi e nella parte inferiore della pagina su telefoni più grandi, considerare l'utilizzo di file di layout diversi e utilizzare qualificatori di risorse per consentire al dispositivo di scegliere il file di layout corretto.
Janusz,

ok .. qual è il punto del secondo paragrafo della risposta qui? "Dovresti trovare un layout che copre prima la parte inferiore dello schermo"? allora dovremmo usare layout_alignParentBottom all'interno del layout? Di cosa abbiamo bisogno android:layout_above?
Eugene,

È necessario quanto sopra se si desidera qualcosa di simile a una barra nella parte inferiore e quindi un layout lineare sopra questa barra che si estende dalla parte superiore dello schermo alla barra.
Janusz,

1
Ho letto in uno di "Android Weekly" che that RelativeLayoutconsuma memoria e dovrebbe essere evitato ogni volta che è possibile.
Tomasz Mularczyk,

153

In ScrollViewquesto non funziona, poiché RelativeLayoutsi sovrapporrebbero a ciò che è nella ScrollViewparte inferiore della pagina.

L'ho corretto usando uno stiramento dinamico 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>

1
è fantastico, inoltre è "minimamente invasivo" e più intuitivo dell'approccio RelativeLayout. Darei più di un voto se potessi!
manmal

4
Uso la tua soluzione nella mia applicazione, ma nel mio caso voglio che quando appare la tastiera, i pulsanti rimangano nella parte inferiore dello schermo (dietro la tastiera) C'è un avvertimento per questo? Thaks.
Yoann

1
@DoubleYo: nel manifest android: windowSoftInputMode = "AdjustPan"
Kopfgeldjaeger

2
Se vuoi che il fondo sia fissato in modo permanente in modo che sia mostrato tutto il tempo che non funziona. Altrimenti funziona.
K - La tossicità in SO sta crescendo.

72

È possibile mantenere il layout lineare iniziale annidando il layout relativo all'interno del layout lineare:

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

2
Questo è un approccio disordinato in quanto non è molto modulare. Non dovresti avere layout sovrapposti. Questo design non funzionerà non appena si desidera modificare lo sfondo di RelativeLayout o si desidera ingrandire una delle visualizzazioni o aggiungere visualizzazioni.
Patrick,

42

La risposta sopra (di Janusz) è abbastanza corretta, ma personalmente non mi sento al 100% a mio agio con RelativeLayouts, quindi preferisco introdurre un TextView vuoto e riempitivo, come questo:

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

prima dell'elemento che dovrebbe essere nella parte inferiore dello schermo.


Si espanderà sull'asse x o y. Dare 0dip per l'altezza renderà la visualizzazione del testo senza alcuna altezza? o si espanderà tanto quanto può piacere all'asse x?
Lukap,

Questo si espande in verticale perché l'altezza (asse verticale) è impostata su 0 e il peso su 1 (presupponendo che gli altri elementi abbiano un peso zero).
Timores,

Sull'asse x, sarà come genitore (fill_parent)
Timores,

Piuttosto che una visualizzazione testuale userei un altro layout lineare. Vista layout sembra implicare che può essere utilizzato per riempire lo spazio?
Vieni il

33

Puoi farlo anche con LinearLayout o ScrollView. A volte è più facile da implementare di un RelativeLayout. L'unica cosa che devi fare è aggiungere la seguente vista prima delle Viste che vuoi allineare nella parte inferiore dello schermo:

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

Questo crea una vista vuota, riempiendo lo spazio vuoto e spingendo le viste successive nella parte inferiore dello schermo.


27

Questo funziona anche.

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

gravità = "bottom" per far galleggiare gli elementi LinearLayout verso il basso


12
android: layout_alignParentBottom = "true" non ha alcun effetto a meno che LinearLayout non sia nidificato in un RelativeLayout.
Thomas Dignan,

Una spiegazione sarebbe in ordine (ad esempio, il cambiamento essenziale, come funziona, perché funziona, ecc.).
Peter Mortensen,

26

1. Usa ConstraintLayoutnel tuo layout di root

E imposta app:layout_constraintBottom_toBottomOf="parent"per lasciare il layout nella parte inferiore dello schermo:

<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. Utilizzare FrameLayoutnel layout di root

Basta impostare android:layout_gravity="bottom"nel layout

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

3. Usa LinearLayoutnel tuo layout di root ( android:orientation="vertical")

(1) Imposta un layout android:layout_weight="1"nella parte superiore del layout

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

(2) Impostare il bambino LinearLayoutperandroid:layout_width="match_parent" android:layout_height="match_parent" android:gravity="bottom"

L'attributo principale è ndroid:gravity="bottom", lascia che il figlio visualizzi nella parte inferiore del layout.

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

4. Utilizzare RelativeLayoutnel layout principale

E imposta android:layout_alignParentBottom="true"per lasciare il layout nella parte inferiore dello schermo

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

Produzione

Inserisci qui la descrizione dell'immagine


20

In seguito all'elegante soluzione di Timores , ho scoperto che quanto segue crea un riempimento verticale in un LinearLayout verticale e un riempimento orizzontale in un LinearLayout orizzontale:

<Space
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1" />

@sepehr Ci deve essere un altro fattore in gioco nel caso in cui hai trovato dove la mia soluzione non funziona. Ho appena provato la mia soluzione in un layout frammentato e funziona anche lì.
stevehs17,

i pesi sono supportati in layout lineari e @sepehr funzioneranno anche in frammenti, attività, notifiche, dialoghi;)
Jan Rabe

16

Non è nemmeno necessario nidificare il secondo relativelayout all'interno del primo. Usa semplicemente android:layout_alignParentBottom="true"il pulsante e EditText .


Solo una nota che sebbene funzioni con Button e EditText, se provassi ad allineare un TableLayout in questo modo non funzionerebbe. Dovresti annidarlo all'interno di un altro RelativeLayout.

11

Se non desideri apportare molte modifiche, puoi semplicemente inserire:

android:layout_weight="1"

per TextView con ID come @+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>

Oppure aggiungi un LinearLayout circostante con Android: layout_weight = "1" - funziona anche all'interno di ScrollView!
bk138,

7

Creando intestazione e piè di pagina , ecco un esempio:

XML layout

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

Immagine dello schermo

Inserisci qui la descrizione dell'immagine


4

Usa il codice qui sotto. Allinea il pulsante al pulsante. Sta funzionando.

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

3

Per un caso come questo, utilizzare sempre RelativeLayouts. Un LinearLayout non è destinato a tale utilizzo.

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

2

Usa android:layout_alignParentBottom="true" nel tuo <RelativeLayout>.

Questo sarà sicuramente di aiuto.


1
Ciò presume che l'utente desideri utilizzare un RelativeLayout.
IgorGanapolsky,

2

Nel caso tu abbia una gerarchia come questa:

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

In primo luogo, applicare android:fillViewport="true"al ScrollViewe quindi applicare android:layout_alignParentBottom="true"al LinearLayout.

Questo ha funzionato perfettamente per me.

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

2

Si può solo dare al vostro bambino vista dall'alto (la TextView @ + id / TextView ) un attributo: android:layout_weight="1".

Questo forzerà tutti gli altri elementi sottostanti verso il basso.


2

Questo può essere fatto anche con un layout lineare.

Fornisci solo Height = 0dp e weight = 1 al layout sopra e quello che vuoi in fondo. Basta scrivere height = avvolgere il contenuto e senza peso.

Fornisce contenuto a capo per il layout (quello che contiene il testo e il pulsante di modifica) e quindi quello con peso occupa il resto del layout.

L'ho scoperto per caso.


0

Ho usato la soluzione pubblicata da Janusz, ma ho aggiunto il riempimento all'ultima vista poiché la parte superiore del mio layout era una ScrollView.

ScrollView sarà parzialmente nascosto man mano che cresce con il contenuto. L'utilizzo android:paddingBottomnell'ultima vista consente di mostrare tutto il contenuto in ScrollView.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.