Como alinhar as vistas na parte inferior da tela?

636

Aqui está o meu código de 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>

O que parece está à esquerda e o que eu quero que esteja à direita.

Layout do Android - real (esquerda) e desejado (direita)

A resposta óbvia é definir o TextView como fill_parent na height, mas isso não deixa espaço para o botão ou campo de entrada.

Essencialmente, o problema é que eu quero que o botão enviar e a entrada de texto tenham uma altura fixa na parte inferior e a exibição de texto para preencher o restante do espaço. Da mesma forma, no layout linear horizontal, desejo que o botão enviar envolva seu conteúdo e que a entrada de texto preencha o restante do espaço.

Se o primeiro item em um layout linear é solicitado a fill_parent, ele faz exatamente isso, não deixando espaço para outros itens. Como obtenho um item que é o primeiro em um layout linear para preencher todo o espaço além do mínimo exigido pelo restante dos itens no layout?


Layouts relativos foram de fato a resposta:

    <?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
fonte
7
@oneself Pintura;) Eu estou usando um skin no emulador embora cortesia de chá Vui Huang teavuihuang.com/android
GAV
14
+1 para postar o XML do layout que o resolveu. Me ajudou a descobrir o que havia de errado com o meu.
30412 Howler

Respostas:

527

A maneira moderna de fazer isso é ter um ConstraintLayout e restringir a parte inferior da visualização à parte inferior do ConstraintLayout comapp:layout_constraintBottom_toBottomOf="parent"

O exemplo abaixo cria um FloatingActionButton que será alinhado ao final e à parte inferior da tela.

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

Para referência, vou manter minha antiga resposta.

Antes da introdução do ConstraintLayout, a resposta era um layout relativo .


Se você tiver um layout relativo que preencha a tela inteira, poderá usar android:layout_alignParentBottomo botão para mover o botão para a parte inferior da tela.

Se suas vistas na parte inferior não forem mostradas em um layout relativo, talvez o layout acima ocupe todo o espaço. Nesse caso, você pode colocar a visualização, que deve estar na parte inferior, primeiro no arquivo de layout e posicionar o restante do layout acima das visualizações android:layout_above. Isso permite que a visualização inferior ocupe o espaço necessário e o restante do layout pode preencher todo o restante da tela.

Janusz
fonte
5
FYI: isso não funcionaria dentro de um ScrollView. Este é o problema que estou enfrentando agora. Veja stackoverflow.com/questions/3126347/…
IgorGanapolsky
6
Isso é correto, ScrollViews e Relative Layouts não combinam muito bem. Se você tiver muito conteúdo para exibir tudo em uma página, use um layout linear e coloque a vista inferior por último. Se você deseja que a exibição apareça por último na visualização de rolagem em telas pequenas e na parte inferior da página em telefones maiores, considere usar arquivos de layout diferentes e use qualificadores de recursos para permitir que o dispositivo escolha o arquivo de layout correto.
Janusz
ok .. qual é o objetivo do segundo parágrafo da resposta aqui? "Você deve encontrar um layout que cubra a parte inferior da tela primeiro"? então devemos usar layout_alignParentBottom dentro do layout? Para que precisamos android:layout_above?
Eugene
Você precisa do acima, se quiser algo como uma barra na parte inferior e, em seguida, um LinearLayout acima dessa barra que se estende da parte superior da tela até a barra.
Janusz
1
Eu li em um dos "Android Weekly" that RelativeLayoutestá consumindo memória e deve ser evitado sempre que possível.
Tomasz Mularczyk
153

Em um exemplo, ScrollViewisso não funciona, pois o RelativeLayoutarquivo se sobrepõe ao que está na ScrollViewparte inferior da página.

Corrigi-o usando um alongamento 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
fonte
1
isso é ótimo - além disso, é "mínimo invasivo" e mais intuitivo que a abordagem RelativeLayout. Eu daria mais de um voto positivo se pudesse!
manmal
4
Eu uso sua solução no meu aplicativo, mas, no meu caso, quero que, quando o teclado aparecer, os botões fiquem na parte inferior da tela (atrás do teclado). Thaks.
Yoann
1
@ DoubleYo: no manifesto android: windowSoftInputMode = "AdjustPan"
Kopfgeldjaeger
2
SE você deseja que a parte inferior seja fixada permanentemente, para que seja exibida o tempo todo, isso não funcione. Caso contrário, funciona.
K - A toxicidade no SO está crescendo.
72

Você pode manter seu layout linear inicial, aninhando o layout relativo no layout linear:

<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
fonte
2
Essa é uma abordagem confusa, pois não é muito modular. Você não deve ter layouts sobrepostos. Esse design não funcionará assim que você desejar alterar o plano de fundo do RelativeLayout ou aumentar ou aumentar qualquer uma das visualizações.
Patrick
42

A resposta acima (de Janusz) é bastante correta, mas eu pessoalmente não me sinto 100% confortável com RelativeLayouts, por isso prefiro introduzir um TextView vazio 'preenchedor', assim:

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

antes do elemento que deve estar na parte inferior da tela.

Timores
fonte
Isso vai se expandir para o eixo x ou y. Dar 0dip para altura fará com que o texto seja visualizado sem altura? ou expandirá o máximo que puder para o eixo x?
Lukap
Isso se expande verticalmente porque a altura (eixo vertical) é definida como 0 e o peso como 1 (assumindo que outros elementos tenham peso zero).
Timores 10/08/11
No eixo x, será como seu pai (fill_parent)
Timores
Em vez de uma visualização de texto, eu usaria outro layout linear. A exibição de layout parece implicar que pode ser usada para preencher espaço?
ComeIn
33

Você pode fazer isso com um LinearLayout ou um ScrollView também. Às vezes, é mais fácil de implementar do que um RelativeLayout. A única coisa que você precisa fazer é adicionar a seguinte exibição antes das exibições que você deseja alinhar na parte inferior da tela:

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

Isso cria uma vista vazia, preenchendo o espaço vazio e empurrando as próximas vistas para a parte inferior da tela.

keybee
fonte
27

Isso também 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 flutuar os elementos LinearLayout para baixo

Michael Reed
fonte
12
android: layout_alignParentBottom = "true" não tem efeito, a menos que o LinearLayout esteja aninhado dentro de um RelativeLayout.
Thomas Dignan
Uma explicação estaria em ordem (por exemplo, a mudança essencial, como funciona, por que funciona etc.).
Peter Mortensen
26

1. Use ConstraintLayoutem seu layout raiz

E defina app:layout_constraintBottom_toBottomOf="parent"para deixar o Layout na parte inferior da tela:

<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. Use FrameLayoutem seu layout raiz

Basta definir android:layout_gravity="bottom"no seu 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. Use LinearLayoutem seu layout raiz ( android:orientation="vertical")

(1) Defina um layout android:layout_weight="1"na parte superior do seu Layout

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

(2) Defina a criança LinearLayoutparaandroid:layout_width="match_parent" android:layout_height="match_parent" android:gravity="bottom"

O principal atributo é ndroid:gravity="bottom", deixe o filho Visualizar na parte inferior do Layout.

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

4. Use RelativeLayoutno layout raiz

E defina android:layout_alignParentBottom="true"para deixar o Layout na parte inferior da tela

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

Resultado

Digite a descrição da imagem aqui

KeLiuyue
fonte
20

Seguindo a solução elegante de Timores , descobri que o seguinte cria um preenchimento vertical em um LinearLayout vertical e um preenchimento horizontal em um LinearLayout horizontal:

<Space
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1" />
stevehs17
fonte
@sepehr Deve haver outro fator em jogo no caso de você encontrar onde minha solução não funciona. Eu apenas tentei minha solução em um layout de fragmento e funciona lá também.
stevehs17
pesos são suportados em esquemas lineares e @sepehr eles vão trabalhar em fragmentos, as actividades, as comunicações, bem como caixas de diálogo;)
Jan Rabe
16

Você nem precisa aninhar o segundo relativelayout dentro do primeiro. Basta usar o android:layout_alignParentBottom="true"no botão e EditText .

Steve Haley
fonte
Apenas observe que, embora isso funcione com o Button e o EditText, se você tentar alinhar um TableLayout dessa maneira, não funcionará. Você precisaria aninhar dentro de outro RelativeLayout.
11

Se você não deseja fazer muitas alterações, basta colocar:

android:layout_weight="1"

para o TextView com 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
fonte
Ou adicione um LinearLayout ao redor com android: layout_weight = "1" - isso também funciona bem dentro de um ScrollView!
bk138
7

Criando cabeçalho e rodapé , aqui está um exemplo:

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

Captura de tela

Digite a descrição da imagem aqui

Madan Sapkota
fonte
4

Use o código abaixo. Alinhe o botão ao botão. Está 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
fonte
3

Para um caso como esse, sempre use RelativeLayouts. Um LinearLayout não se destina a esse 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.
fonte
2

Use android:layout_alignParentBottom="true" no seu <RelativeLayout>.

Isso definitivamente vai ajudar.

jigar
fonte
1
Isso pressupõe que o usuário deseja usar um RelativeLayout.
IgorGanapolsky
2

Caso você tenha uma hierarquia como esta:

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

Primeiro, aplique android:fillViewport="true"ao ScrollViewe depois android:layout_alignParentBottom="true"ao LinearLayout.

Isso funcionou para mim perfeitamente.

<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>
Principe
fonte
2

Você pode apenas dar a sua visão superior da criança (o TextView @ + id / TextView ) um atributo: android:layout_weight="1".

Isso forçará todos os outros elementos abaixo para baixo.

IgorGanapolsky
fonte
2

Isso também pode ser feito com um layout linear.

Basta fornecer Altura = 0dp e peso = 1 para o layout acima e o desejado na parte inferior. Basta escrever a altura = conteúdo do invólucro e sem peso.

Ele fornece conteúdo de quebra automática para o layout (aquele que contém o texto e o botão de edição) e, em seguida, aquele que tem peso ocupa o restante do layout.

Eu descobri isso por acidente.

raihan ahmed
fonte
0

Usei a solução que Janusz postou, mas adicionei preenchimento à última visualização, pois a parte superior do meu layout era um ScrollView.

O ScrollView ficará parcialmente oculto à medida que cresce com o conteúdo. O uso android:paddingBottomda última visualização ajuda a mostrar todo o conteúdo no ScrollView.

jeremyvillalobos
fonte