¿Qué es android: weightSum en android y cómo funciona?

Respuestas:

133

Según la documentación, android:weightSumdefine la suma máxima de peso y se calcula como la suma layout_weightde todos los elementos secundarios si no se especifica explícitamente.

Consideremos un ejemplo con a LinearLayoutcon orientación horizontal y 3 ImageViewsdentro de él. Ahora queremos que estos ImageViewssiempre tomen el mismo espacio. Para lograr esto, puede establecer el valor layout_weightde cada uno ImageViewen 1 y weightSumse calculará igual a 3 como se muestra en el comentario.

<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 es útil para que el diseño se represente correctamente para cualquier dispositivo, lo que no sucederá si establece el ancho y la altura directamente.

superM
fuente
145
Esta no es una explicación del propósito de weightSum. El comportamiento en su ejemplo sería idéntico al weightSumomitido, y de hecho weightSum no debería especificarse en ese escenario. La documentación diceweightSum 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: ¿"no debería" especificarse? ¿Por qué? No veo ninguna razón para eso. Entonces, solo diría que no es necesario especificarlo.
grazna
17
@MarcoW .: No debe especificarse debido a la capacidad de mantenimiento. Como dijo Jeff, establecer el weightSum para que sea igual a la suma de los pesos dentro del diseño no logra nada, pero si alguien lo cambia en el futuro podría causar dolores de cabeza ya que ahora hay un modificador innecesario del diseño que debería encontrarse y cambiado Esta respuesta es incorrecta y no debe ser la respuesta aceptada.
d370urn3ur
3
No veo una buena explicación del parámetro weightSum, así que de los documentos: "Esto se puede usar, por ejemplo, para dar a un solo niño el 50% del espacio total disponible al asignarle un layout_weight de 0.5 y establecer el weightSum en 1.0". Ver developer.android.com/reference/android/widget/…
Deepscorn
55
La idea es que puede establecer weightSum en un número más alto que la suma de los hijos. Esto hace que los niños reciban parte pero no todo el espacio extra disponible. En el ejemplo anterior, su hijo soltero heredaría la mitad del espacio disponible en lugar de todo.
Edward Falk
175

Agregando a la respuesta de superM y Jeff,

Si hay 2 vistas en LinearLayout, la primera con un layout_weight de 1, la segunda con un layout_weight de 2 y sin weightSum, de forma predeterminada, el weightSum se calcula en 3 (suma de los pesos de los hijos) y la primera vista ocupa 1/3 del espacio, mientras que la segunda ocupa 2/3.

Sin embargo, si tuviéramos que especificar el weightSum como 5, el primero tomaría 1/5 del espacio mientras que el segundo tomaría 2/5. Por lo tanto, un total de 3/5 del espacio estaría ocupado por el diseño manteniendo el resto vacío.

Shubhayu
fuente
2
Estaba buscando lo mismo, que pasaría si weightsum no está definido y los pesos se proporcionan a las vistas secundarias. Su respuesta que calcula es propia, lo borró todo
DeltaCap019
¿Es cierto que se recomienda usar RelativeLayout que Layouts con weightSum?
Robert
26

La suma de peso funciona exactamente como lo desea (como otras respuestas, no tiene que sumar todos los pesos en el diseño principal). En la vista secundaria, especifique el peso que desea que tome. No olvides especificar

android:layout_width="0dp" 

El siguiente es un ejemplo

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

Esto se verá como

ingrese la descripción de la imagen aquí

Asomó a Buzz
fuente
25

La documentación lo dice mejor e incluye un ejemplo (destacando el mío).

android: weightSum

Define la suma máxima de peso. Si no se especifica, la suma se calcula sumando el layout_weight de todos los elementos secundarios. Esto se puede usar, por ejemplo, para dar a un niño solo el 50% del espacio total disponible al asignarle un layout_weight de 0.5 y establecer el weightSum en 1.0.

Entonces, para corregir el ejemplo de superM, suponga que tiene una LinearLayoutorientación horizontal que contiene dos ImageViewsy una TextViewcon. Defina TextViewque tiene un tamaño fijo y desea que los dos ImageViewsocupen el espacio restante por igual.

Para lograr esto, aplicaría layout_weight1 a cada uno ImageView, ninguno en el TextView, y un weightSum2.0 en el LinearLayout.

Jeff Axelrod
fuente
20

Después de experimentar un poco, creo que el algoritmo para LinearLayout es este:

Suponga que weightSumse establece en un valor. El caso de ausencia se discute más adelante.

Primero, divida el weightSumpor el número de elementos con match_parento fill_parenten la dimensión de LinearLayout (por ejemplo, layout_widthfor orientation="horizontal"). Llamaremos a este valor el multiplicador de peso w_mpara cada elemento. El valor predeterminado para weightSumes 1.0, entonces el multiplicador de peso predeterminado es 1/n, donde nes el número de fill_parentelementos; wrap_contentelementos no contribuyen a n.

w_m = weightSum / #fill_parent

Por ejemplo, cuando weightSumes 60 y hay 3 fill_parentelementos, el multiplicador de peso es 20. El multiplicador de peso es el valor predeterminado para, por ejemplo, layout_widthsi el atributo está ausente.

En segundo lugar, se calcula la máxima expansión posible de cada elemento. Primero, los wrap_contentelementos se calculan de acuerdo con sus contenidos. Su expansión se deduce de la expansión del contenedor principal. Llamaremos al remanente expansion_remainer. Este resto se distribuye entre los fill_parentelementos según su layout_weight.

Tercero, la expansión de cada fill_parentelemento se calcula como:

w_m - (layout_weight / w_m) * maximum_possible_expansion

Ejemplo:

Si weightSumes 60, y hay 3 fill_parentelementos con los pesos 10, 20 y 30, su expansión en la pantalla es 2/3, 1/3 y 0/3 del contenedor principal.

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

La expansión mínima está limitada a 0. La expansión máxima está limitada al tamaño principal, es decir, los pesos están limitados a 0.

Si un elemento se establece en wrap_content, su expansión se calcula primero, y la expansión restante está sujeta a distribución entre los fill_parentelementos. Si weightSumse establece, esto lleva a layout_weightno tener efecto sobre los wrap_contentelementos Sin embargo, los wrap_contentelementos aún pueden ser empujados fuera del área visible por elementos cuyo peso es menor que multiplicador de peso(por ejemplo, entre 0-1 para weightSum= 1 o entre 0-20 para el ejemplo anterior).

Si no weightSumse especifica, se calcula como la suma de todos los layout_weightvalores, incluidos los elementos con wrap_contentset! Por lo tanto, haber layout_weightestablecido wrap_contentelementos puede influir en su expansión. Por ejemplo, un peso negativo reducirá los otros fill_parentelementos. Antes de presentar los fill_parentelementos, la fórmula anterior se aplicará a los wrap_contentelementos, siendo la expansión máxima posible su expansión de acuerdo con el contenido envuelto. Los wrap_contentelementos se reducirán, y luego fill_parentse calculará y distribuirá la máxima expansión posible para los elementos restantes .

Esto puede conducir a resultados poco intuitivos.

Jens Jensen
fuente
10

Si no se especifica, la suma se calcula sumando el layout_weight de todos los elementos secundarios. Esto se puede usar, por ejemplo, para dar a un solo hijo el 50% del espacio total disponible al asignarle un layout_weight de 0.5 y establecer el weightSum en 1.0. Debe ser un valor de coma flotante, 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
fuente
'Puede ser un valor de coma flotante, como "1.2". ( developer.android.com/reference/android/widget/… )
El increíble Jan
6

Una cosa que parece que nadie más mencionó: digamos que tiene una vertical LinearLayout , por lo que para que los pesos en diseño / elemento / vista funcionen al 100% correctamente, todos deben tener layout_heightpropiedades (que deben existir en su xml archivo) establecido en 0dp. Parece que cualquier otro valor arruinaría las cosas en algunos casos.

Yoav Feuerstein
fuente
1
android: layout_width = "match_parent" se usa generalmente en lugar de 0dp
kc ochibili
¿por qué es así? Quiero decir que tienes razón, es un desastre, pero establecer la altura a 0 dp solucionó mi problema. Me gustaría saber la razón.
Abdul Waheed
2

Layout Weight funciona como una relación. Por ejemplo, si hay un diseño vertical y hay dos elementos (como botones o vistas de texto), uno con un peso de diseño 2 y el otro con un peso de diseño 3, respectivamente. Luego, el primer elemento ocupará 2 de 5 porciones de la pantalla / diseño y el otro 3 de 5 porciones. Aquí 5 es la suma de peso. es decir, la suma de peso divide todo el diseño en porciones definidas. Y el Peso de diseño define la cantidad de porción que ocupa un artículo en particular de la Suma de peso total predefinida. La suma de peso también se puede declarar manualmente. Los botones, las vistas de texto, los textos de edición, etc., todos se organizan utilizando la suma de peso y el peso del diseño cuando se utilizan diseños lineales para el diseño de la interfaz de usuario.

Sami Al-Jabar
fuente
1

De la documentación del desarrollador

Esto se puede usar, por ejemplo, para dar a un solo hijo 50%del espacio total disponible dándole un layout_weight de 0.5y estableciendo el weightSum en 1.0.

Además de la respuesta @Shubhayu

El resto 3/5se puede utilizar para otros diseños secundarios que realmente no necesitan ninguna parte específica del diseño que contiene.

Este es el uso potencial de la android:weightSumpropiedad.

DjP
fuente