Что такое андроид: весовая сумма в андроиде и как она работает? - PullRequest
145 голосов
/ 17 сентября 2011

Хочу узнать: что такое android: weightSum и layout layout и как они работают?

Ответы [ 9 ]

167 голосов
/ 08 октября 2012

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

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

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

114 голосов
/ 17 сентября 2011

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

23 голосов
/ 04 октября 2012

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

android: weightSum

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

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

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

22 голосов
/ 27 июня 2016

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

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>

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

enter image description here

19 голосов
/ 08 апреля 2014

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

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

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

w_m = weightSum / #fill_parent

например. когда weightSum равно 60 и имеется 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

* +1039 * Пример:

Если weightSum равно 60, и есть 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 могут по-прежнему выталкиваться из видимой области элементами, вес которых меньше weight multiplier (например, между 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.

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

9 голосов
/ 16 апреля 2013

Если не указано, сумма рассчитывается путем добавления 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>
6 голосов
/ 06 августа 2014

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

1 голос
/ 11 мая 2016

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

1 голос
/ 29 марта 2016

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

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

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

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

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

...