é possível distribuir botões uniformemente pela largura de um layout linear do Android

247

Eu tenho um layout linear (orientado horizontalmente) que contém 3 botões. Quero que os 3 botões tenham uma largura fixa e sejam distribuídos uniformemente pela largura do layout linear.

Eu posso gerenciar isso definindo a gravidade do layout linear para o centro e depois ajustando o preenchimento dos botões, mas isso funciona para uma largura fixa e não para alterações de dispositivos ou orientações.

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

<Button 
android:id="@+id/btnOne"
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:width="120dip"></Button>

<Button 
android:id="@+id/btnTwo"
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:width="120dip"></Button>


<Button 
android:id="@+id/btnThree"
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:width="120dip"></Button>

</LinearLayout>
yamspog
fonte

Respostas:

339

Expandindo resposta das fedj , se você definir layout_widtha 0dpe definir o layout_weightpara cada um dos botões para 1, a largura disponível serão divididos igualmente entre os botões.

Dan Dyer
fonte
81
Para expandir isso, se você não quiser que a largura dos botões seja 1/3 da tela, envolva cada botão em um LinearLayout e defina layout_width = "0dp" e layout_weight = "1" nos 3 LinearLayouts. Além disso, defina a gravidade nos LinearLayouts como "center" para que os botões se alinhem no centro de cada LinearLayout.
12133 Andrew
este é o caso para LinearLayout only.can qualquer um dar alguma ideia para equispacing em RelativeLayout
user1859771
1
No meu caso, eu uso layout_width = "wrap_content" e apenas com layout_weight = "1" funciona bem!
27515 StefanM5
Isso não está correto, pois o OP deseja consertar. Veja a resposta de stoefln.
Mitulát Bati
228

Se você não deseja que os botões sejam redimensionados, mas ajuste o espaçamento entre os botões (espaçamento igual entre todos os botões), você pode usar vistas com peso = "1" que preencherá o espaço entre os botões:

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

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:background="@null"
        android:gravity="center_horizontal|center_vertical"
        android:src="@drawable/tars_active" />

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

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:background="@null"
        android:gravity="center_horizontal|center_vertical"
        android:src="@drawable/videos_active" />

    <Space
        android:layout_width="0dp"
        android:layout_height="1dp"
        android:layout_weight="1" >
    </Space>
stoefln
fonte
15
Esse é definitivamente o método de sobrecarga mais simples e mais baixo que funciona (no caso em que você deseja que o espaço entre as visualizações seja escalado, não as próprias). Estou usando verticalmente e, portanto, apenas troquei os valores de largura e altura. Obrigado.
Samis
7
Esta é uma solução elegante. Você pode preferir usar o Spacetipo de exibição. Torna as coisas um pouco mais legíveis.
Ryan R
2
Ryan, sim, se você estiver usando a API 14+ (como deveríamos).
Eduardo Naveda
Honestamente, eu pensei que não funcionaria quando tivesse 4 botões, mas funcionou brilhantemente sem barulho e medição de tempo de execução. Respeito!
Ashraf Alshahawy
Isso é melhor do que o aceito atualmente como resposta.
DroidHeaven
25

Você pode usá-lo da seguinte forma.

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:layout_marginTop="15dp">
    <Space
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Save"/>
    <Space
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Reset"/>
    <Space
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="cancel"/>
    <Space
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"/>
</LinearLayout>
Sandhu
fonte
isso é vassoura !! Eu nunca ouvi falar Spaceaté agora
Someone Somewhere
21

Você pode fazer isso dando tanto Viewsa layout_widthda 0dpe uma layout_weightde 1:

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

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

    <TextView
        android:layout_width="0dp"
        android:text="example text"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>

</LinearLayout>

A maneira como o android layout_weight funciona é:

  • primeiro, ele olha para o tamanho que uma visualização normalmente levaria e reserva esse espaço.
  • segundo, se o layout for match_parent, ele dividirá o espaço restante na proporção de layout_weights. Portanto, se você deu as vistas layout_weight="2"e layout_weight="1", a proporção resultante será de 2 para 1, ou seja: a primeira vista receberá 2/3 do espaço restante e a outra vista 1/3.

É por isso que, se você fornecer layout_widthum tamanho da 0dpprimeira etapa, não terá um significado adicional, já que os dois modos de exibição não receberão nenhum espaço. Então, apenas o segundo ponto decide o espaço que cada um Viewobtém, dando a Views o espaço especificado de acordo com a proporção!

Para explicar por 0dpque o espaço é dividido igualmente, fornecendo um exemplo que mostra o oposto: O código abaixo resultaria em algo diferente, pois example textagora tem uma largura maior do que 0dpporque, ao wrap_contentinvés disso, deixou o espaço livre para dividir menos de 100% porque o texto ocupa espaço. O resultado será que eles obterão 50% do espaço livre restante, mas o texto já TextViewocupará algum espaço, de modo que terá mais de 50% do espaço total.

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

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

    <TextView
        android:layout_width="wrap_content"
        android:text="example text"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>

</LinearLayout>
Joop
fonte
13

Bem, se você tiver exatamente 3 botões e se estiver ok (ou até planejado) que os botões externos estejam alinhados aos lados esquerdo e direito, convém tentar um RelativeLayout que seja menos sobrecarga (em muitas situações).

Você pode usar layout_alignParentBottompara alinhar todos os botões com a parte inferior do layout. Use layout_alignParentLeft and Rightpara os botões externos e layout_centerHorizontalpara o botão do meio.

Isso funcionará bem em diferentes orientações e tamanhos de tela.

marsbear
fonte
Para esclarecer, isso não funciona se você tiver mais de três botões.
Arlomedia
Exatamente. Você precisaria usar um LinearLayout ou RadioGroup (se aplicável).
Marsbear
11

Você deve dar uma olhada no android: atributo layout_weight

fedj
fonte
1
Entendi que o atributo layout_weight aumentará o tamanho do botão para preencher o layout. Quero manter o tamanho dos botões constante e apenas aumentar o preenchimento entre os botões.
yamspog
Ah! Eu realmente não sei a melhor maneira de fazê-lo. Talvez colocando cada botão no layout. O layout 3 com o atributo layout_weight e o botão centralizado no layout. Mas eu realmente não sei se é a melhor maneira de fazê-lo.
fedj
9

A solução moderna para isso é o Flexbox .

<com.google.android.flexbox.FlexboxLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:justifyContent="space_around"> <!-- or "space_between", "space_evenly" -->

    <Button 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:width="120dp" />

    <Button 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:width="120dp" />

    <Button 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:width="120dp" />
</com.google.android.flexbox.FlexboxLayout>

Certifique-se de importar implementation 'com.google.android:flexbox:2.0.0'

Flexboxé muito mais poderoso; é um bom complemento para ConstraintLayout. Este é um ótimo recurso para aprender mais.

Diferença entre space_around, space_between e space_evenly

Gibolt
fonte
1
obrigado por me informar. Definitivamente útil. Eu usei "space_around" e os botões estavam bem centralizados quando eu tinha 1 ou 3 visíveis no FlexBox
Someone Somewhere
4

Para espaçar uniformemente dois botões em um layout linear horizontal, usei 3 objetos LinearLayout para atuar como espaços que serão redimensionados automaticamente. Posicionei esses objetos LinearLayout da seguinte maneira:

[] Botão1 [] Botão2 []

([] representa um objeto LinearLayout usado para espaçamento)

então defino o peso de cada um desses objetos [] LinearLayout como 1 e recebo botões espaçados igualmente.

Espero que isto ajude.

Maomé
fonte
4

Sugiro que você use o atributo weightSum de LinearLayout.

Adicionar a tag android:weightSum="3"à declaração xml do LinearLayout e, em seguida, android:layout_weight="1"aos Buttons resultará na distribuição uniforme dos 3 botões.

matdev
fonte
4

Isso pode ser conseguido atribuindo weighta cada botão adicionado dentro do contêiner, muito importante para definir a orientação horizontal:

    int buttons = 5;

    RadioGroup rgp = (RadioGroup) findViewById(R.id.radio_group);

    rgp.setOrientation(LinearLayout.HORIZONTAL);

    for (int i = 1; i <= buttons; i++) {
        RadioButton rbn = new RadioButton(this);         
        rbn.setId(1 + 1000);
        rbn.setText("RadioButton" + i);
        //Adding weight
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 1f);
        rbn.setLayoutParams(params);
        rgp.addView(rbn);
    }

para que possamos obter isso em nosso dispositivo como resultado:

insira a descrição da imagem aqui

mesmo que rotacionemos nosso dispositivo, o weightdefinido em cada botão pode distribuir os elementos uniformemente ao longo do contêiner:

insira a descrição da imagem aqui

Jorgesys
fonte
3

A melhor abordagem é usar TableLayout com android: layout_width = "match_parent" e nas colunas usar android: layout_weight = "1" para todas as colunas

Prashant
fonte
2

As respostas acima usando layout_d não funcionaram para mim, mas o seguinte funcionou.

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:layout_weight="0.1"
    android:layout_gravity="center_horizontal"
    >

    <android.support.design.widget.FloatingActionButton
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_gravity="center"
       />

    <android.support.design.widget.FloatingActionButton
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:layout_marginLeft="40dp"
        android:layout_marginStart="40dp"/>

    <android.support.design.widget.FloatingActionButton
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:layout_marginLeft="40dp"
        android:layout_marginStart="40dp"
        />

    <android.support.design.widget.FloatingActionButton
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:layout_marginLeft="40dp"
        android:layout_marginStart="40dp"/>

</LinearLayout>

É assim que fica na tela,

insira a descrição da imagem aqui

Sean Le Roy
fonte
2

Acima de todas as respostas, as respostas estão corretas, mas, em um caso, você precisa de recursos visíveis e passados, esse método pragmaticamente funcionará bem

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnOne"
            android:layout_width="120dp"
            android:layout_height="match_parent"></Button>

        <Button
            android:id="@+id/btnTwo"
            android:layout_width="120dp"
            android:layout_height="match_parent"></Button>


        <Button
            android:id="@+id/btnThree"
            android:layout_width="120dp"
            android:layout_height="match_parent"></Button>
    </LinearLayout>



 float width=CommonUtills.getScreenWidth(activity);
            int cardWidth=(int)CommonUtills.convertDpToPixel (((width)/3),activity);

LinearLayout.LayoutParams params =
                new LinearLayout.LayoutParams(width,
                        LinearLayout.LayoutParams.MATCH_PARENT);

btnOne.setLayoutParams(params);
btnTwo.setLayoutParams(params);
btnThree.setLayoutParams(params);

public class CommonUtills {
public static float getScreenWidth(Context context) {
        float width = (float) 360.0;
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        width = displayMetrics.widthPixels / displayMetrics.density;
        return width;
    }
}
Rajesh Nasit
fonte
2

Crianças com o mesmo peso

Para criar um layout linear no qual cada filho use a mesma quantidade de espaço na tela, defina o android: layout_height de cada visualização como "0dp" (para um layout vertical) ou o android: layout_width de cada visualização para "0dp" ( para um layout horizontal). Em seguida, defina o android: layout_weight de cada visualização como "1".

Para que isso funcione no LinearLayoutgrupo de vistas, os valores dos atributos android:layout_widthe android:layout_heightprecisam ser iguais a "match_parent"...

Gibran Castillo
fonte
Graças uma tonelada companheiro! Economizou muito tempo.
Xonshiz 26/04
1
Sem problemas, companheiro.
Gibran Castillo
0
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="Tom"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="24sp" 
        android:layout_weight="3"/>

    <TextView
        android:text="Tim"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="24sp"
        android:layout_weight="3"/>

    <TextView
        android:text="Todd"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="24sp" 
        android:layout_weight="3"/>

</LinearLayout>

Em círculo, Tom, Tim e Todd assumem 3 centímetros. Se você quiser que seja uma tela de toque, coloque-o como Tom e Tim assumindo 1 centímetro, o que significa que eles combinam virtual, mas seu plano 2D está na parte inferior. Isso é exibido na tela.

Dinesh Gowd
fonte
0
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<TextView
    android:text="Tom"
    android:layout_width="wrap_content"
    android:layout_height="200dp"
    android:textSize="24sp" />

<TextView
    android:text="Tim"
    android:layout_width="wrap_content"
    android:layout_height="200dp"
    android:textSize="24sp" />

<TextView
    android:text="Todd"
    android:layout_width="wrap_content"
    android:layout_height="200dp"
    android:textSize="24sp" />

basem
fonte
0

A maneira mais fácil e rápida (mas não a melhor) é adicionar um TextView com atributo de texto vazio, como este

android:text=""

a cor do plano de fundo deve ser a mesma no LinearLayout, você pode usar a propriedade padding, como esta

android:paddingBottom="250dp"

ou o que você precisar. Aqui está um exemplo.

Cesar Bobadilla
fonte