Что такое андроид: весовая сумма в андроиде и как она работает?

Ответы:

133

Согласно документации, android:weightSumопределяется максимальная сумма веса и рассчитывается как сумма layout_weightвсех детей, если не указано явно.

Давайте рассмотрим пример с LinearLayoutгоризонтальной ориентацией и 3 ImageViewsвнутри. Теперь мы хотим, чтобы они ImageViewsвсегда занимали одинаковое пространство. Чтобы добиться этого, вы можете установить layout_weightдля каждого ImageViewзначение 1, и weightSumбудет рассчитано равным 3, как показано в комментарии.

<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 полезно для правильного отображения макета для любого устройства, что не произойдет, если вы установите ширину и высоту напрямую.

superM
источник
145
Это не объяснение цели weightSum. Поведение в вашем примере будет идентичным weightSumопущенному, и фактически в этом сценарии не следует указывать weightSum. Документация говорит,weightSum Defines the maximum weight sum. If unspecified, the sum is computed by adding the layout_weight of all of the children.
Джефф Аксельрода
3
@JeffAxelrod: "не" должно быть указано? Зачем? Я не вижу причин для этого. Так что я бы просто сказал, что это не нужно указывать.
каркай
17
@ MarcoW .: Не следует указывать из-за ремонтопригодности. Как сказал Джефф, установка weightSum равной сумме весов внутри макета ничего не дает, но если кто-то изменит его в будущем, это может вызвать головную боль, так как теперь в макете есть ненужный модификатор, который нужно найти и изменился. Этот ответ неверен и не должен быть принятым ответом.
d370urn3ur
3
Не вижу хорошего объяснения параметра weightSum, поэтому из документации: «Это можно использовать, например, чтобы дать одному ребенку 50% от общего доступного пространства, задав ему layout_weight 0,5 и установив weightSum равным 1,0». См developer.android.com/reference/android/widget/...
Deepscorn
5
Идея состоит в том, что вы можете установить weightSum на число, превышающее сумму детей. Это заставляет детей получать некоторое, но не все доступное дополнительное пространство. В приведенном выше примере ваш единственный ребенок унаследует половину доступного пространства вместо всего этого.
Эдвард Фальк
175

Добавление к ответам SuperM и Джеффа,

Если в LinearLayout есть 2 представления: первое с layout_weight, равным 1, второе с layout_weight, равным 2, и без указания weightSum, по умолчанию weightSum рассчитывается как 3 (сумма весов дочерних элементов) и первый вид занимает 1/3 пространства, а второй - 2/3.

Однако, если бы мы указали весовую сумму 5, первое заняло бы 1/5-ю часть пространства, а второе заняло бы 2/5-е. Таким образом, в общей сложности 3/5 пространства будет занимать макет, оставляя оставшиеся пустыми.

Shubhayu
источник
2
Я искал то же самое: что если весовая сумма не определена, а веса предоставлены дочерним представлениям. Ваш ответ, что он самостоятельно вычисляет все очищенное
DeltaCap019
Правда ли, что рекомендуется использовать RelativeLayout, чем Layouts с weightSum?
Роберт
26

Весовая сумма работает точно так, как вы хотите (как и другие ответы, вам не нужно суммировать все веса на родительском макете). В поле зрения ребенка укажите вес, который вы хотите принять. Не забудьте указать

android:layout_width="0dp" 

Ниже приведен пример

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

Это будет выглядеть

введите описание изображения здесь

Asok Buzz
источник
25

Документация говорит , что лучше , и включает в себя пример, (подсветка шахты).

андроид: weightSum

Определяет максимальную весовую сумму. Если не указано, сумма вычисляется путем добавления layout_weight для всех дочерних элементов. Это можно использовать, например, чтобы дать одному ребенку 50% от общего доступного пространства, задав ему layout_weight 0,5 и установив weightSum равным 1,0.

Итак, чтобы исправить пример superM, предположим, что у вас есть LinearLayoutгоризонтальная ориентация, которая содержит два ImageViewsи a TextViewс. Вы определяете, TextViewчтобы иметь фиксированный размер, и вы хотите, чтобы эти два занимали ImageViewsоставшееся пространство одинаково.

Для этого вы должны применить layout_weight1 к каждому ImageView, ни один для TextView, и weightSum2,0 для LinearLayout.

Джефф Аксельрод
источник
20

После некоторых экспериментов я думаю, что алгоритм для LinearLayout такой:

Предположим, что weightSumустановлено значение. Случай отсутствия обсуждается позже.

Во- первых, разделить weightSumна количество элементов ти match_parentили fill_parentв размерности LinearLayout (например , layout_widthдля orientation="horizontal"). Мы назовем это значение множителем веса w_mдля каждого элемента. Значение по умолчанию для weightSum1.0 - это, следовательно, множитель веса по умолчанию 1/n, где n- количество fill_parentэлементов; wrap_contentэлементы не способствуют n.

w_m = weightSum / #fill_parent

Например, когда weightSum60, и есть 3 fill_parentэлемента, множитель веса равен 20. Умножитель веса является значением по умолчанию, например, layout_widthесли атрибут отсутствует.

Во-вторых, максимально возможное расширение каждого элемента вычисляется. Во-первых, wrap_contentэлементы вычисляются в соответствии с их содержанием. Их расширение вычитается из расширения родительского контейнера. Мы позвоним оставшемуся expansion_remainer. Этот остаток распределяется между fill_parentэлементами в соответствии с их layout_weight.

В-третьих, расширение каждого fill_parentэлемента вычисляется как:

w_m - (layout_weight / w_m) * Maximum_possible_expansion

Пример:

Если weightSum60, и есть 3 fill_parentэлемента с весами 10, 20 и 30, их расширение на экране составляет 2/3, 1/3 и 0/3 родительского контейнера.

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

Минимальное расширение ограничено 0. Максимальное расширение ограничено родительским размером, то есть веса ограничены 0.

Если для элемента установлено значение wrap_content, его расширение рассчитывается первым, а оставшееся расширение подлежит распределению между fill_parentэлементами. Если weightSumустановлено, это приводит к layout_weightотсутствию влияния на wrap_contentэлементы. Тем не менее, wrap_contentэлементы все еще могут быть вытолкнуты из видимой области элементами, вес которых меньше, чем весовой множитель(например, между 0-1 для weightSum= 1 или между 0-20 для приведенного выше примера).

Если значение не weightSumуказано, оно вычисляется как сумма всех layout_weightзначений, включая элементы с wrap_contentмножеством! Так что layout_weightнастроившись на wrap_contentэлементы, можете влиять на их расширение. Например, отрицательный вес сократит другие fill_parentэлементы. Перед размещением fill_parentэлементов будет ли применена вышеуказанная формула к wrap_contentэлементам, причем максимально возможное расширение будет их расширением в соответствии с упакованным содержимым. Эти wrap_contentэлементы будут усадка, а затем максимально возможное расширение для оставшихся fill_parentэлементов вычисляются и распределено.

Это может привести к неинтуитивным результатам.

Дженс Дженсен
источник
10

Если не указано, сумма вычисляется путем добавления layout_weight для всех дочерних элементов. Это можно использовать, например, чтобы дать одному ребенку 50% от общего доступного пространства, задав ему layout_weight 0,5 и установив weightSum равным 1,0. Должно быть значением с плавающей запятой, например, «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
источник
'Может быть значением с плавающей запятой, таким как "1.2".' ( developer.android.com/reference/android/widget/… )
невероятное
6

Одна вещь, которая, кажется, больше никому не упоминалась: допустим, у вас есть вертикаль LinearLayout , поэтому, чтобы веса в компоновке / элементе / представлении внутри нее работали на 100% должным образом - все они должны иметь layout_heightсвойство (которое должно существовать в вашем XML файл) 0dp. Похоже, что любое другое значение может испортить ситуацию в некоторых случаях.

Йоав Фейерштейн
источник
1
android: layout_width = "match_parent" обычно используется вместо 0dp
kc ochibili
Почему это так? Я имею в виду, что вы правы, это все портит, но установка высоты в 0 dp устранила мою проблему. Я хотел бы знать причину.
Абдул Вахид
2

Макет Веса работает как соотношение. Например, если есть вертикальная компоновка и есть два элемента (например, кнопки или текстовые представления), один из которых имеет вес макета 2, а другой имеет вес 3 макета соответственно. Тогда 1-й элемент займет 2 из 5 частей экрана / макета, а другой - 3 из 5 частей. Здесь 5 - весовая сумма. т.е. сумма веса делит весь макет на определенные части. А вес макета определяет, какую долю занимает конкретный элемент из общей заранее определенной суммы веса. Весовая сумма также может быть указана вручную. Кнопки, текстовые представления, edittexts и т. Д. Все организованы с использованием веса и веса макета при использовании линейных макетов для дизайна пользовательского интерфейса.

Сами Аль-Джабар
источник
1

Из документации разработчика

Это может использоваться, например, чтобы дать одному дочернему 50%элементу общего доступного пространства, присвоив ему layout_weight of 0.5и установив weightSum в 1.0.

Дополнение к @Shubhayu ответу

Остальные 3/5могут быть использованы для других дочерних макетов, которые действительно не нуждаются в какой-либо определенной части размещения макета.

это потенциальное использование android:weightSumимущества.

DJP
источник