Qu'est-ce qu'Android: WeightSum dans Android et comment ça marche?

Réponses:

133

Par documentation, android:weightSumdéfinit la somme de poids maximum et est calculée comme la somme layout_weightde tous les enfants si elle n'est pas spécifiée explicitement.

Prenons un exemple avec une LinearLayoutorientation horizontale et 3 à l' ImageViewsintérieur. Maintenant, nous voulons que ceux-ci ImageViewsprennent toujours la même place. Pour y parvenir, vous pouvez définir le layout_weightde chacun ImageViewsur 1 et le weightSumsera calculé pour être égal à 3 comme indiqué dans le commentaire.

<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 est utile pour rendre la mise en page correctement pour n'importe quel appareil, ce qui ne se produira pas si vous définissez directement la largeur et la hauteur.

superM
la source
145
Ce n'est pas une explication de l'objectif de weightSum. Le comportement de votre exemple serait identique à weightSumomis et, en fait, weightSum ne doit pas être spécifié dans ce scénario. La documentation dit,weightSum 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: Il "ne devrait pas" être spécifié? Pourquoi? Je ne vois aucune raison à cela. Je dirais donc simplement qu'il n'est pas nécessaire de le préciser.
caw
17
@MarcoW .: Il ne doit pas être spécifié pour des raisons de maintenabilité. Comme Jeff l'a dit, définir le weightSum comme étant égal à la somme des poids à l'intérieur de la mise en page ne sert à rien, mais si quelqu'un le modifie à l'avenir, cela pourrait causer des maux de tête, car il y a maintenant un modificateur inutile de la mise en page qui devrait être trouvé. et changé. Cette réponse est incorrecte et ne devrait pas être la réponse acceptée.
d370urn3ur
3
Je ne vois pas une bonne explication du paramètre weightSum, donc dans la documentation: "Cela peut être utilisé par exemple pour donner à un seul enfant 50% de l'espace total disponible en lui donnant un layout_weight de 0,5 et en définissant le weightSum sur 1.0." Voir developer.android.com/reference/android/widget/…
Deepscorn
5
L'idée est que vous pouvez définir weightSum sur un nombre supérieur à la somme des enfants. Cela amène les enfants à recevoir une partie mais pas la totalité de l'espace supplémentaire disponible. Dans l'exemple ci-dessus, votre enfant unique hériterait de la moitié de l'espace disponible au lieu de la totalité.
Edward Falk
175

En plus de la réponse de superM et de Jeff,

S'il y a 2 vues dans LinearLayout, la première avec un layout_weight de 1, la seconde avec un layout_weight de 2 et aucun weightSum n'est spécifié, par défaut, le weightSum est calculé à 3 (somme des poids des enfants) et la première vue occupe 1/3 de l'espace tandis que la seconde prend 2/3.

Cependant, si nous devions spécifier le weightSum comme 5, le premier prendrait 1 / 5ème de l'espace tandis que le second prendrait 2 / 5ème. Ainsi, un total de 3 / 5ème de l'espace serait occupé par la mise en page gardant le reste vide.

Shubhayu
la source
2
Je cherchais la même chose, que se passe-t-il si la somme de poids n'est pas définie et que des poids sont fournis aux vues de l'enfant. Votre réponse qu'il calcule lui-même a tout effacé
DeltaCap019
Est-il vrai qu'il est recommandé d'utiliser RelativeLayout plutôt que Layouts avec weightSum?
Robert
26

La somme des poids fonctionne exactement comme vous le souhaitez (comme pour les autres réponses, vous n'avez pas à additionner tous les poids sur la mise en page parent). Sur la vue enfant, spécifiez le poids que vous voulez qu'il prenne. N'oubliez pas de préciser

android:layout_width="0dp" 

Voici un exemple

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

Cela ressemblera à

entrez la description de l'image ici

asok Buzz
la source
25

La documentation le dit le mieux et comprend un exemple (mettant en évidence le mien).

android: weightSum

Définit la somme de poids maximum. S'il n'est pas spécifié, la somme est calculée en ajoutant le layout_weight de tous les enfants. Cela peut être utilisé par exemple pour donner à un seul enfant 50% de l'espace total disponible en lui attribuant un layout_weight de 0,5 et en définissant weightSum sur 1.0.

Donc, pour corriger l'exemple de superM, supposons que vous ayez un LinearLayoutavec une orientation horizontale qui contient deux ImageViewset un TextViewavec. Vous définissez le TextViewpour avoir une taille fixe et vous souhaitez que les deux ImageViewsoccupent également l'espace restant.

Pour ce faire, appliquez layout_weight1 à chacun ImageView, aucun sur le TextViewet un weightSumde 2,0 sur le LinearLayout.

Jeff Axelrod
la source
20

Après quelques expérimentations, je pense que l'algorithme de LinearLayout est le suivant:

Supposons qu'il weightSumsoit défini sur une valeur. Le cas d'absence est discuté plus loin.

Commencez par diviser le weightSumpar le nombre d'éléments avec match_parentou fill_parentdans la dimension du LinearLayout (par exemple layout_widthpour orientation="horizontal"). Nous appellerons cette valeur le multiplicateur de poids w_mpour chaque élément. La valeur par défaut de weightSumest 1.0, donc le multiplicateur de poids par défaut est 1/n, où nest le nombre d' fill_parentéléments; wrap_contentéléments ne contribuent pas à n.

w_m = weightSum / #fill_parent

Par exemple, quand weightSumvaut 60 et qu'il y a 3 fill_parentéléments, le multiplicateur de poids est 20. Le multiplicateur de poids est la valeur par défaut pour, par exemple, layout_widthsi l'attribut est absent.

Deuxièmement, l'expansion maximale possible de chaque élément est calculée. Tout d'abord, les wrap_contentéléments sont calculés en fonction de leur contenu. Leur expansion est déduite de l'expansion du conteneur parent. Nous appellerons le reste expansion_remainer. Ce reste est réparti entre les fill_parentéléments selon leurlayout_weight .

Troisièmement, l'expansion de chaque fill_parentélément est calculée comme suit:

w_m - (layout_weight / w_m) * maximum_possible_expansion

Exemple:

Si weightSumvaut 60, et qu'il y a 3 fill_parentéléments de poids 10, 20 et 30, leur expansion sur l'écran est de 2/3, 1/3 et 0/3 du conteneur parent.

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

L'expansion minimale est plafonnée à 0. L'expansion maximale est plafonnée à la taille du parent, c'est-à-dire que les poids sont plafonnés à 0.

Si un élément est défini sur wrap_content, son expansion est calculée en premier et l'expansion restante est sujette à une distribution entre les fill_parentéléments. Si weightSumest défini, cela conduit à layout_weightn'avoir aucun effet sur les wrap_contentéléments. Cependant, les wrap_contentéléments peuvent encore être poussés hors de la zone visible par des éléments dont le poids est inférieur à multiplicateur de poids(par exemple entre 0-1 pourweightSum = 1 ou entre 0-20 pour l'exemple ci-dessus).

Si non weightSumest spécifié, il est calculé comme la somme de toutes les layout_weightvaleurs, y compris les éléments avec wrap_contentset! Donc, avoir layout_weightmis sur des wrap_contentéléments, peut influencer leur expansion. Par exemple, un poids négatif réduira les autres fill_parentéléments. Avant que les fill_parentéléments ne soient disposés, la formule ci-dessus sera appliquée aux wrap_contentéléments, l'expansion maximale possible étant leur expansion en fonction du contenu emballé. Les wrap_contentéléments seront réduits, et ensuite l'expansion maximale possible pour les fill_parentéléments restants est calculée et distribuée.

Cela peut conduire à des résultats peu intuitifs.

Jens Jensen
la source
10

S'il n'est pas spécifié, la somme est calculée en ajoutant le layout_weight de tous les enfants. Ceci peut être utilisé par exemple pour donner à un seul enfant 50% de l'espace total disponible en lui donnant un layout_weight de 0,5 et en définissant le weightSum sur 1.0. Doit être une valeur à virgule flottante, telle que "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
la source
"Peut être une valeur à virgule flottante, telle que" 1,2 "." ( developer.android.com/reference/android/widget/… )
L'incroyable
6

Une chose qui semble que personne d'autre n'a mentionné: disons que vous avez une verticale LinearLayout , donc pour que les poids dans la mise en page / l'élément / la vue à l'intérieur fonctionnent à 100% correctement - ils doivent tous avoir une layout_heightpropriété (qui doit exister dans votre xml file) défini sur 0dp. Il semble que toute autre valeur gâcherait les choses dans certains cas.

Yoav Feuerstein
la source
1
android: layout_width = "match_parent" est généralement utilisé au lieu de 0dp
kc ochibili
pourquoi est-ce si? Je veux dire que vous avez raison, c'est gâcher, mais régler la hauteur à 0 dp a résolu mon problème. je voudrais connaître la raison.
Abdul Waheed
2

Le poids de la mise en page fonctionne comme un rapport. Par exemple, s'il existe une disposition verticale et qu'il y a deux éléments (tels que des boutons ou des vues de texte), l'un ayant un poids de mise en page 2 et l'autre un poids de mise en page 3 respectivement. Ensuite, le premier élément occupera 2 parties sur 5 de l'écran / mise en page et l'autre 3 sur 5 parties. Ici, 5 est la somme des poids. c'est-à-dire que la somme de poids divise la mise en page entière en portions définies. Et le poids de mise en page définit la portion occupée par l'élément particulier par rapport à la somme de poids totale prédéfinie. La somme des poids peut également être déclarée manuellement. Les boutons, les vues de texte, les edittexts, etc. sont tous organisés à l'aide de la pondération et du poids de la mise en page lors de l'utilisation de mises en page linéaires pour la conception de l'interface utilisateur.

Sami Al-Jabar
la source
1

De la documentation du développeur

Cela peut être utilisé par exemple pour donner à un seul enfant 50%de l'espace total disponible en lui donnant un layout_weight de 0.5et en définissant le weightSum sur 1.0.

Ajout à la réponse @Shubhayu

rest 3/5peut être utilisé pour d'autres mises en page enfants qui n'ont vraiment pas besoin d'une partie spécifique de la mise en page contenant.

il s'agit d'une utilisation potentielle de la android:weightSumpropriété.

DjP
la source