Co to jest android: weightSum w systemie Android i jak to działa?

Odpowiedzi:

133

Według dokumentacji android:weightSumokreśla maksymalną sumę wag i jest obliczana jako suma layout_weightwszystkich elementów podrzędnych, jeśli nie została wyraźnie określona.

Rozważmy przykład z LinearLayoutorientacją poziomą i 3 w ImageViewsśrodku. Teraz chcemy, aby ImageViewszawsze zajmowały równą przestrzeń. Aby to osiągnąć, możesz ustawić layout_weightkażdy ImageViewna 1, a weightSumzostanie obliczony jako równy 3, jak pokazano w komentarzu.

<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 przydaje się do prawidłowego renderowania układu dla dowolnego urządzenia, co nie nastąpi, jeśli bezpośrednio ustawisz szerokość i wysokość.

superM
źródło
145
To nie jest wyjaśnienie celu weightSum. Zachowanie w twoim przykładzie byłoby identyczne z weightSumpominiętym i faktycznie weightSum nie powinno być określane w tym scenariuszu. Dokumentacja mówiweightSum 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: „Nie powinno” być określone? Czemu? Nie widzę powodu. Więc powiedziałbym tylko, że nie trzeba tego określać.
krakanie
17
@MarcoW .: Nie należy go określać ze względu na łatwość konserwacji. Jak powiedział Jeff, ustawienie weightSum na równą sumie wag wewnątrz layoutu nic nie daje, ale jeśli ktoś zmieni to w przyszłości, może to spowodować ból głowy, ponieważ teraz jest niepotrzebny modyfikator do układu, który musiałby zostać znaleziony i zmieniony. Ta odpowiedź jest nieprawidłowa i nie powinna być akceptowaną odpowiedzią.
d370urn3ur
3
Nie widzę dobrego wyjaśnienia parametru weightSum, więc z dokumentacji: „Można to wykorzystać na przykład, aby dać pojedynczemu dziecku 50% całkowitej dostępnej przestrzeni, nadając mu layout_weight na 0,5 i ustawiając weightSum na 1,0.” Zobacz developer.android.com/reference/android/widget/…
Deepscorn
5
Chodzi o to, że możesz ustawić weightSum na liczbę wyższą niż suma dzieci. To powoduje, że dzieci otrzymują część dostępnej dodatkowej przestrzeni, ale nie całą. W powyższym przykładzie Twoje samotne dziecko odziedziczy połowę dostępnego miejsca zamiast całego.
Edward Falk
175

Dodając do odpowiedzi superM i Jeffa,

Jeśli w LinearLayout znajdują się 2 widoki, pierwszy z wartością layout_weight równą 1, drugi z wartością layout_weight równą 2 i bez parametru weightSum, domyślnie weightSum jest obliczana na 3 (suma wag elementów podrzędnych) i pierwszy widok zajmuje 1/3 powierzchni, a drugi 2/3.

Gdybyśmy jednak mieli określić wagę sumy jako 5, pierwsza zajęłaby 1/5 przestrzeni, a druga 2/5. Zatem w sumie 3/5 powierzchni byłaby zajęta przez układ, pozostawiając pustą resztę.

Shubhayu
źródło
2
Szukałem tego samego, co, jeśli waga nie jest zdefiniowana, a wagi są podane do widoków dziecka. Twoja odpowiedź, że oblicza własne, wyczyściła wszystko
DeltaCap019
Czy to prawda, że ​​zaleca się używanie RelativeLayout niż Layouts z weightSum?
Robert
26

Suma wag działa dokładnie tak, jak chcesz (podobnie jak w przypadku innych odpowiedzi nie musisz sumować wszystkich wag w układzie nadrzędnym). W widoku podrzędnym określ, jaką wagę ma przyjąć. Nie zapomnij określić

android:layout_width="0dp" 

Oto przykład

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

To będzie wyglądać

wprowadź opis obrazu tutaj

asok Buzz
źródło
25

Dokumentacja mówi, że najlepiej i zawiera przykładowe (pokazujące moje).

android: weightSum

Określa maksymalną sumę wag. Jeśli nie zostanie określony, suma jest obliczana przez dodanie layoutu_weight wszystkich elementów podrzędnych. Można to wykorzystać na przykład do przydzielenia jednemu dziecku 50% całkowitej dostępnej przestrzeni, nadając mu layout_weight równy 0,5 i ustawiając weightSum na 1,0.

Aby poprawić przykład superM, załóżmy, że masz element LinearLayoutz orientacją poziomą, który zawiera dwa ImageViewsi TextViewz. Definiujesz, TextViewaby mieć stały rozmiar i chcesz, aby te dwa ImageViewsrówno zajmowały pozostałe miejsce.

Aby to osiągnąć, zastosowałbyś layout_weight1 do każdego ImageView, żadnego na TextViewi weightSum2,0 na LinearLayout.

Jeff Axelrod
źródło
20

Po kilku eksperymentach myślę, że algorytm LinearLayout wygląda tak:

Załóżmy, że weightSumjest ustawiony na wartość. Przypadek nieobecności zostanie omówiony później.

Najpierw podziel weightSumprzez liczbę elementów z match_parentlub fill_parentw wymiarze LinearLayout (np. layout_widthDla orientation="horizontal"). Wartość tę nazwiemy mnożnikiem wagi w_mdla każdego elementu. Wartość domyślna weightSumto 1.0, więc domyślny mnożnik wagi to 1/n, gdzie njest liczbą fill_parentelementów; wrap_contentelementy nie przyczyniają się do n.

w_m = wagaSum / #fill_parent

Np. Gdy weightSumwynosi 60 i są 3 fill_parentelementy, mnożnik wagi wynosi 20. Mnożnik wagi jest wartością domyślną, np. W layout_widthprzypadku braku atrybutu.

Po drugie, obliczana jest maksymalna możliwa ekspansja każdego elementu. Najpierw wrap_contentelementy są obliczane zgodnie z ich zawartością. Ich rozszerzenie jest odejmowane od rozwinięcia kontenera nadrzędnego. Pozostałych zadzwonimy expansion_remainer. Ta reszta jest rozdzielana między fill_parentelementy zgodnie z ich layout_weight.

Po trzecie, rozwinięcie każdego fill_parentelementu jest obliczane jako:

w_m - (ciężar_układu / w_m) * maksymalny_możliwy_rozszerzenie

Przykład:

Jeśli weightSumwynosi 60 i są 3 fill_parentelementy o wadze 10, 20 i 30, ich rozwinięcie na ekranie wynosi 2/3, 1/3 i 0/3 pojemnika nadrzędnego.

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

Minimalna ekspansja jest ograniczona do 0. Maksymalna ekspansja jest ograniczona do rozmiaru rodzica, tj. Wagi są ograniczone do 0.

Jeśli element jest ustawiony na wrap_content, jego rozwinięcie jest obliczane jako pierwsze, a pozostała ekspansja podlega dystrybucji między fill_parentelementy. Jeśli weightSumjest ustawiona, prowadzi to do layout_weightbraku wpływu na wrap_contentelementy. Jednak wrap_contentelementy mogą być nadal wypychane z widocznego obszaru przez elementy, których waga jest mniejsza niż mnożnik wagi(np. Między 0-1 dla weightSum= 1 lub między 0-20 dla powyższego przykładu).

Jeśli nie weightSumokreślono, jest obliczana jako suma wszystkich layout_weightwartości, w tym elementów z wrap_contentustawieniem! Tak więc layout_weightnastawienie na wrap_contentżywioły może wpłynąć na ich ekspansję. Np. Ujemna waga zmniejszy pozostałe fill_parentelementy. Czy przed rozłożeniem fill_parentelementów powyższa formuła zostanie zastosowana do wrap_contentelementów, przy czym maksymalnym możliwym rozszerzeniem będzie ich rozszerzanie się zgodnie z opakowaną zawartością. Te wrap_contentelementy będą skurczony, po czym maksymalna możliwa ekspansji dla pozostałych fill_parentelementów jest obliczana i rozdzielone.

Może to prowadzić do nieintuicyjnych wyników.

Jens Jensen
źródło
10

Jeśli nie zostanie określony, suma jest obliczana przez dodanie layoutu_weight wszystkich elementów podrzędnych. Można to wykorzystać na przykład do przydzielenia jednemu dziecku 50% całkowitej dostępnej przestrzeni, nadając mu layout_weight równy 0,5 i ustawiając weightSum na 1,0. Musi być wartością zmiennoprzecinkową, np. „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
źródło
„Może być wartością zmiennoprzecinkową, na przykład„ 1,2 ”.” ( developer.android.com/reference/android/widget/… )
Niesamowity Jan
6

Jedna rzecz, o której nikt inny nie wspomniał: powiedzmy, że masz pion LinearLayout , więc aby wagi w układzie / elemencie / widoku wewnątrz działały w 100% - wszystkie muszą mieć layout_heightwłaściwość (która musi istnieć w twoim xml file) ustawione na 0dp. Wydaje się, że każda inna wartość może w niektórych przypadkach zepsuć sprawę.

Yoav Feuerstein
źródło
1
android: layout_width = "match_parent" jest zwykle używane zamiast 0dp
kc ochibili
dlaczego to jest takie? Mam na myśli, że masz rację, to się psuje, ale ustawienie wysokości na 0 dp rozwiązało mój problem. chciałbym znać powód.
Abdul Waheed
2

Waga układu działa jak współczynnik. Na przykład, jeśli istnieje układ pionowy i są tam dwa elementy (takie jak przyciski lub widoki tekstu), jeden ma wagę układu 2, a drugi odpowiednio wagę układu 3. Wtedy pierwsza pozycja zajmie 2 z 5 części ekranu / układu, a druga 3 z 5 części. Tutaj 5 to suma wag. tzn. suma wag dzieli cały układ na określone porcje. A Layout Weight (waga układu) określa, jaką część zajmuje dany przedmiot z całkowitej wstępnie zdefiniowanej sumy wag. Sumę wagi można również zadeklarować ręcznie. Przyciski, podglądy tekstu, edittexty itp. Są zorganizowane przy użyciu wagi i wagi układu podczas korzystania z układów liniowych do projektowania interfejsu użytkownika.

Sami Al-Jabar
źródło
1

Z dokumentacji programisty

Można to wykorzystać na przykład do nadania pojedynczemu podrzędnemu 50%całkowitej dostępnej przestrzeni, nadając mu layout_weight 0.5i ustawiając weightSum na 1.0.

Dodatek do odpowiedzi @Shubhayu

reszta 3/5może być używana dla innych układów potomnych, które naprawdę nie wymagają żadnej określonej części układu zawierającego.

jest to potencjalne wykorzystanie android:weightSumwłasności.

DjP
źródło