O que é android: weightSum no android e como ele funciona?

Respostas:

132

Por documentação, android:weightSumdefine a soma máxima de peso e é calculada como a soma layout_weightde todos os filhos, se não especificado explicitamente.

Vamos considerar um exemplo com a LinearLayoutcom orientação horizontal e 3 ImageViewsdentro dela. Agora queremos que eles ImageViewssempre ocupem espaço igual. Para conseguir isso, você pode definir o valor layout_weightde cada um ImageViewpara 1 e o valor weightSumserá calculado para ser igual a 3, conforme mostrado no comentário.

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    <!-- android:weightSum="3" -->
    android:orientation="horizontal"
    android:layout_gravity="center">

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

weightSum é útil por ter o layout renderizado corretamente para qualquer dispositivo, o que não acontecerá se você definir largura e altura diretamente.

superM
fonte
145
Esta não é uma explicação do objetivo de weightSum. O comportamento no seu exemplo seria idêntico ao weightSumomitido e, de fato, weightSum não deve ser especificado nesse cenário. A documentação dizweightSum Defines the maximum weight sum. If unspecified, the sum is computed by adding the layout_weight of all of the children.
Jeff Axelrod
3
@JeffAxelrod: "Não deve" ser especificado? Por quê? Não vejo razão para isso. Então, eu apenas diria que não precisa ser especificado.
caw
17
@MarcoW .: Não deve ser especificado por causa da manutenção. Como Jeff disse, definir o weightSum como igual à soma dos pesos dentro do layout não faz nada, mas se alguém o alterar no futuro, isso poderá causar dores de cabeça, pois agora há um modificador desnecessário no layout que teria que ser encontrado e mudou. Esta resposta está incorreta e não deve ser a resposta aceita.
precisa saber é o seguinte
3
Não veja uma boa explicação do parâmetro weightSum; portanto, nos documentos: "Isso pode ser usado, por exemplo, para fornecer a um único filho 50% do espaço total disponível, fornecendo um layout_weight de 0,5 e configurando o weightSum para 1,0". Veja developer.android.com/reference/android/widget/…
Deepscorn
5
A idéia é que você pode definir weightSum para um número maior que a soma dos filhos. Isso faz com que as crianças recebam um pouco, mas não todo o espaço extra disponível. No exemplo acima, seu filho único herdaria metade do espaço disponível em vez de todo.
Edward Falk
175

Adicionando à resposta de superM e Jeff,

Se houver duas visualizações no LinearLayout, a primeira com um layout_weight de 1, a segunda com um layout_weight de 2 e nenhum weightSum for especificado, por padrão, o weightSum será calculado como 3 (soma dos pesos dos filhos) e a primeira visualização ocupa 1/3 do espaço, enquanto a segunda ocupa 2/3.

No entanto, se especificarmos o weightSum como 5, o primeiro ocupará 1/5 do espaço, enquanto o segundo ocupará 2/5. Assim, um total de 1/5 do espaço seria ocupado pelo layout, mantendo o restante vazio.

Shubhayu
fonte
2
Eu estava procurando o mesmo, que e se o peso do peso não estiver definido e o peso for fornecido para as visualizações filho. A sua resposta que ele calcula possuir o seu próprio tudo limpo
DeltaCap019
É verdade que é recomendável usar RelativeLayout do que Layouts com weightSum?
Robert
26

A soma do peso funciona exatamente como você deseja (como outras respostas, você não precisa somar todos os pesos no layout dos pais). Na exibição infantil, especifique o peso que você deseja que ele assuma. Não esqueça de especificar

android:layout_width="0dp" 

A seguir está um exemplo

    <LinearLayout
                android:layout_width="500dp"
                android:layout_height="20dp" >

                <TextView
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="3"
                    android:background="@android:color/holo_green_light"
                    android:gravity="center"
                    android:text="30%"
                    android:textColor="@android:color/white" >
                </TextView>

                <TextView
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="2"
                    android:background="@android:color/holo_blue_bright"
                    android:gravity="center"
                    android:text="20%"
                    android:textColor="@android:color/white" >
                </TextView>

                <TextView
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="5"
                    android:background="@android:color/holo_orange_dark"
                    android:gravity="center"
                    android:text="50%"
                    android:textColor="@android:color/white" >
                </TextView>
 </LinearLayout>

Isso vai parecer

insira a descrição da imagem aqui

perguntou Buzz
fonte
25

A documentação diz o melhor e inclui um exemplo (destacando o meu).

android: weightSum

Define a soma máxima de peso. Se não especificado, a soma é calculada adicionando o peso_de_ layout de todos os filhos. Isso pode ser usado, por exemplo, para fornecer a um único filho 50% do espaço total disponível, fornecendo um layout_weight de 0,5 e configurando o weightSum para 1,0.

Portanto, para corrigir o exemplo de superM, suponha que você tenha uma LinearLayoutorientação horizontal que contenha dois ImageViewse um TextViewcom. Você define TextViewum tamanho fixo e deseja que os dois ImageViewsocupem o espaço restante igualmente.

Para fazer isso, você aplicaria layout_weight1 a cada um ImageView, nenhum no TextViewe um weightSumde 2,0 no LinearLayout.

Jeff Axelrod
fonte
20

Após algumas experiências, acho que o algoritmo para LinearLayout é o seguinte:

Suponha que weightSumesteja definido como um valor. O caso da ausência é discutido mais adiante.

Primeiro, divida o weightSumpelo número de elementos com match_parentou fill_parentna dimensão do LinearLayout (por exemplo, layout_widthpara orientation="horizontal"). Vamos chamar esse valor de multiplicador de peso w_mpara cada elemento. O valor padrão para weightSumé 1,0; portanto, o multiplicador de peso padrão é 1/nonde né o número de fill_parentelementos; wrap_contentelementos não contribuem para n.

w_m = weightSum / #fill_parent

Por exemplo, quando weightSumé 60 e existem 3 fill_parentelementos, o multiplicador de peso é 20. O multiplicador de peso é o valor padrão, por exemplo, layout_widthse o atributo estiver ausente.

Segundo, a expansão máxima possível de cada elemento é calculada. Primeiro, os wrap_contentelementos são calculados de acordo com seu conteúdo. Sua expansão é deduzida da expansão do contêiner pai. Vamos ligar para o restante expansion_remainer. Esse restante é distribuído entre os fill_parentelementos de acordo com os respectivos layout_weight.

Terceiro, a expansão de cada fill_parentelemento é calculada como:

w_m - (peso_de_ layout / w_m) * expansão_possível máxima

Exemplo:

Se weightSumfor 60 e houver 3 fill_parentelementos com os pesos 10, 20 e 30, sua expansão na tela será 2/3, 1/3 e 0/3 do contêiner pai.

weight | expansion
     0 | 3/3
    10 | 2/3
    20 | 1/3
    30 | 0/3
    40 | 0/3

A expansão mínima é limitada a 0. A expansão máxima é limitada ao tamanho pai, ou seja, os pesos são limitados a 0.

Se um elemento estiver definido como wrap_content, sua expansão será calculada primeiro e a expansão restante estará sujeita à distribuição entre os fill_parentelementos. Se weightSumdefinido, isso leva a layout_weightnão ter efeito nos wrap_contentelementos. No entanto, os wrap_contentelementos ainda podem ser empurrados para fora da área visível por elementos cujo peso seja menor que multiplicador de peso(por exemplo, entre 0-1 para weightSum= 1 ou entre 0-20 no exemplo acima).

Se não weightSumfor especificado, será computado como a soma de todos os layout_weightvalores, incluindo elementos com wrap_contentset! Então, tendo layout_weightdefinido wrap_contentelementos, pode influenciar sua expansão. Por exemplo, um peso negativo encolherá os outros fill_parentelementos. Antes de os fill_parentelementos serem dispostos, a fórmula acima será aplicada aos wrap_contentelementos, com a expansão máxima possível sendo sua expansão de acordo com o conteúdo agrupado. Os wrap_contentelementos serão reduzidos e, posteriormente, a expansão máxima possível para os fill_parentelementos restantes é calculada e distribuída.

Isso pode levar a resultados não intuitivos.

Jens Jensen
fonte
10

Se não especificado, a soma é calculada adicionando o peso_de_ layout de todos os filhos. Isso pode ser usado, por exemplo, para fornecer a um único filho 50% do espaço total disponível, fornecendo um layout_weight de 0,5 e configurando o weightSum para 1,0. Deve ser um valor de ponto flutuante, como "1,2"

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/main_rel"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:weightSum="2.0" >

        <RelativeLayout
            android:id="@+id/child_one"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1.0"
            android:background="#0000FF" >
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/child_two"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1.0"
            android:background="#00FF00" >
        </RelativeLayout>

    </LinearLayout>
Faakhir
fonte
'Pode ser um valor de ponto flutuante, como "1,2".' ( developer.android.com/reference/android/widget/… )
o incrível
6

Uma coisa que parece que ninguém mais mencionou: digamos que você tenha uma vertical LinearLayout , portanto, para que os pesos no layout / elemento / visualização dentro dela funcionem 100% corretamente - todos eles devem ter layout_heightpropriedades (que devem existir no seu xml arquivo) definido como 0dp. Parece que qualquer outro valor atrapalharia as coisas em alguns casos.

Yoav Feuerstein
fonte
1
android: layout_width = "match_parent" é geralmente usado em vez de 0dp
kc ochibili
por que? Quero dizer que você está certo, está atrapalhando, mas definir altura como 0 dp solucionou meu problema. eu gostaria de saber o motivo.
Abdul Waheed
2

O peso do layout funciona como uma proporção. Por exemplo, se houver um layout vertical e houver dois itens (como botões ou visualizações de texto), um com peso de layout 2 e outro com peso de layout 3, respectivamente. Em seguida, o 1º item ocupará 2 das 5 partes da tela / layout e o outro 3 das 5 partes. Aqui 5 é a soma do peso. isto é, a soma do peso divide todo o layout em porções definidas. E o Peso do layout define quanta parte o item específico ocupa da soma total de pesos predefinida. A soma de peso também pode ser declarada manualmente. Botões, visualizações de texto, etc, todos os textos são organizados usando peso e peso de layout ao usar layouts lineares para design de interface do usuário.

Sami Al-Jabar
fonte
1

Da documentação do desenvolvedor

Isso pode ser usado, por exemplo, para fornecer um único filho 50%do espaço total disponível, fornecendo a ele um layout_weight 0.5e definindo o weightSum como 1.0.

Além da resposta @Shubhayu

o resto 3/5pode ser usado para outros layouts filhos que realmente não precisam de nenhuma parte específica do layout que contém.

esse é o uso potencial da android:weightSumpropriedade.

DjP
fonte