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

Хочу узнать: что такое андроид: весовая сумма и вес макета, и как они работают?

10 ответов

Решение

По документации, 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 и Джеффа,

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

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

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

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>

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

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

андроид: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,

После некоторых экспериментов я думаю, что алгоритм для 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

Пример:

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

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

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

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

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

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

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

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

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

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

Никто явно не упомянул, что это конкретный XML-атрибут для LinearLayout.

Я считаю, что это будет полезно всем, кто сначала, как и я, был сбит с толку, ища weightSumв ConstraintLayoutдокументация.

Другие вопросы по тегам