Android คืออะไรน้ำหนักใน Android และมันทำงานอย่างไร


คำตอบ:


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 มีประโยชน์สำหรับการจัดวางเลย์เอาต์อย่างถูกต้องสำหรับอุปกรณ์ใด ๆ ซึ่งจะไม่เกิดขึ้นหากคุณตั้งค่าความกว้างและความสูงโดยตรง


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.
เจฟฟ์ Axelrod

3
@JeffAxelrod: มันคือ "ไม่ควรระบุ"? ทำไม? ฉันไม่เห็นเหตุผลว่า ดังนั้นฉันจะบอกว่ามันไม่จำเป็นต้องระบุ
caw

17
@MarcoW: ไม่ควรระบุเนื่องจากการบำรุงรักษา ดังที่เจฟฟ์กล่าวว่าการกำหนดน้ำหนักผลรวมให้เท่ากับผลรวมของน้ำหนักภายในเค้าโครงไม่ทำอะไรเลย แต่ถ้าใครบางคนเปลี่ยนมันในอนาคตอาจทำให้เกิดอาการปวดหัวเนื่องจากตอนนี้มีตัวดัดแปลงที่ไม่จำเป็นสำหรับรูปแบบที่จะต้องพบ และเปลี่ยนไป คำตอบนี้ไม่ถูกต้องและไม่ควรเป็นคำตอบที่ยอมรับได้
d370urn3ur

3
ไม่เห็นคำอธิบายที่ดีของพารามิเตอร์ weightSum ดังนั้นจากเอกสาร: "สิ่งนี้สามารถใช้เพื่อให้เด็กคนเดียว 50% ของพื้นที่ว่างทั้งหมดโดยให้ layout_weight 0.5 และตั้งค่า weightSum เป็น 1.0" ดูdeveloper.android.com/reference/android/widget/…
Deepscorn

5
แนวคิดก็คือคุณสามารถตั้งค่าน้ำหนักผลรวมเป็นจำนวนที่สูงกว่าผลรวมของเด็ก สิ่งนี้ทำให้เด็ก ๆ ได้รับบางส่วน แต่ไม่ทั้งหมดของพื้นที่ว่างที่มีอยู่ ในตัวอย่างด้านบนลูกคนเดียวของคุณจะได้รับครึ่งหนึ่งของพื้นที่ว่างแทนที่จะเป็นทั้งหมด
Edward Falk

175

การเพิ่มคำตอบของ superM และ Jeff

หากมีมุมมอง 2 แบบใน LinearLayout รายการแรกที่มี layout_weight 1, ครั้งที่สองที่มี layout_weight 2 และไม่ระบุ weightSum โดยค่าเริ่มต้น WeightSum จะถูกคำนวณเป็น 3 (ผลรวมของน้ำหนักของเด็ก) และ มุมมองแรกใช้พื้นที่ 1/3 ในขณะที่มุมมองที่สองใช้เวลา 2/3

อย่างไรก็ตามหากเราต้องระบุน้ำหนักผลรวมเป็น 5 อันดับแรกจะใช้เวลา 1 / 5th ของพื้นที่ส่วนที่สองจะใช้ 2 / 5th ดังนั้นพื้นที่ทั้งหมดจะถูกจัดไว้ให้โดยส่วนที่เหลือของส่วนที่เหลือทั้งหมด


2
ฉันกำลังมองหาสิ่งเดียวกันว่าจะทำอย่างไรหากไม่ได้กำหนดน้ำหนักและให้น้ำหนักแก่มุมมองของเด็ก คำตอบของคุณว่ามันคำนวณเองทุกอย่างล้าง
DeltaCap019

เป็นความจริงไหมที่แนะนำให้ใช้ RelativeLayout กว่า Layouts with weightSum
Robert

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>

จะมีลักษณะเช่นนี้

ป้อนคำอธิบายรูปภาพที่นี่


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สำหรับแต่ละองค์ประกอบ ค่าเริ่มต้นสำหรับweightSumคือ 1.0 ดังนั้นตัวคูณน้ำหนักเริ่มต้นคือ1/nโดยที่nจำนวนfill_parentองค์ประกอบ; องค์ประกอบที่ไม่นำไปสู่wrap_contentn

w_m = weightSum / #fill_parent

เช่นเมื่อweightSumเป็น 60 และมี 3 fill_parentองค์ประกอบตัวคูณน้ำหนักคือ 20 ตัวคูณน้ำหนักเป็นค่าเริ่มต้นสำหรับเช่นlayout_widthหากไม่มีแอตทริบิวต์

ประการที่สองการคำนวณการขยายตัวสูงสุดที่เป็นไปได้ของทุกองค์ประกอบ ก่อนwrap_contentองค์ประกอบจะถูกคำนวณตามเนื้อหาของพวกเขา การขยายตัวของพวกเขาจะถูกหักออกจากการขยายตัวของภาชนะแม่ เราจะเรียก expansion_remainerremainer ส่วนที่เหลือนี้ถูกกระจายfill_parentไปตามองค์ประกอบต่างๆlayout_weightต่างๆ

ประการที่สามการขยายตัวของทุกfill_parentองค์ประกอบถูกคำนวณดังนี้

w_m - (layout_weight / w_m) * max_possible_expansion

ตัวอย่าง:

ถ้าweightSum60 และมี 3 fill_parentองค์ประกอบที่มี weigths 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>

'อาจเป็นค่าทศนิยมเช่น "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 ทำให้เกิดปัญหาของฉัน ฉันต้องการทราบเหตุผล
Abdul Waheed

2

น้ำหนักเค้าโครงทำงานเหมือนอัตราส่วน ตัวอย่างเช่นหากมีเลย์เอาต์แนวตั้งและมีสองรายการ (เช่นปุ่มหรือ textviews) รายการหนึ่งมีน้ำหนักโครงร่าง 2 และอีกรายการมีน้ำหนักโครงร่าง 3 ตามลำดับ จากนั้นรายการที่ 1 จะครอบครอง 2 จาก 5 ส่วนของหน้าจอ / เลย์เอาต์และอีกหนึ่ง 3 จาก 5 ส่วน ที่นี่ 5 คือผลรวมน้ำหนัก ie ผลรวมน้ำหนักแบ่งเค้าโครงทั้งหมดเป็นส่วนที่กำหนดไว้ และเลย์เอาต์น้ำหนักจะกำหนดจำนวนไอเท็มเฉพาะที่ครอบครองจากผลรวมของน้ำหนักรวมที่กำหนดไว้ล่วงหน้า ผลรวมน้ำหนักสามารถประกาศด้วยตนเองเช่นกัน ปุ่ม, textviews, edittexts และอื่น ๆ ทั้งหมดได้รับการจัดระเบียบโดยใช้น้ำหนักและรูปแบบน้ำหนักเมื่อใช้รูปแบบเชิงเส้นสำหรับการออกแบบ UI


1

จากเอกสารของนักพัฒนา

นี้สามารถนำมาใช้สำหรับอินสแตนซ์ที่จะช่วยให้ลูกเดียว50%ของพื้นที่ที่มีอยู่ทั้งหมดโดยให้มัน layout_weight ของ0.5และการตั้งค่า weightSum 1.0ไป

นอกเหนือจาก @Shubhayu คำตอบ

ส่วนที่เหลือ3/5สามารถใช้กับเลย์เอาต์ลูกอื่น ๆ ซึ่งไม่ต้องการส่วนที่เฉพาะเจาะจงของการเก็บเลย์เอาต์

นี่คือการใช้android:weightSumทรัพย์สินที่มีศักยภาพ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.