รู้จักกับ Layout Weight ใน Linear Layout
ถึงแม้ว่าโลกของการพัฒนาแอปบนแอนดรอยด์จะเข้าสู่ยุคของการใช้ Constraint Layout หรือเปลี่ยนไปใช้ Jetpack Compose แล้ว แต่ Linear Layout ก็ยังเป็น View Group พื้นฐานที่ใช้กันอยู่ใน UI หลาย ๆ รูปแบบ
และ Layout Weight ก็เป็นหนึ่งใน Attribute สำคัญของ Linear Layout ที่ช่วยให้นักพัฒนาสามารถจัด UI ได้ตรงกับที่ต้องการได้ง่ายขึ้น รองรับ Responsive UI ได้ดีขึ้น ดังนั้นในบทความนี้จะมาพูดถึง Layout Weight ที่อยู่ใน Linear Layout กัน
หน้าที่ของ Layout Weight
Layout Weight ใช้สำหรับกำหนดสัดส่วนของ Weight/Height ของ Child View ตามพื้นที่ว่างที่เหลืออยู่ใน Linear Layout โดยคิดสัดส่วนจาก Child View ทุกตัวที่มีการกำหนดค่า Layout Weight เหมือนกัน
ยกตัวอย่างเช่น ต้องการจัด UI โดยให้ Child View มีความกว้างเท่ากันทั้งหมด โดยไม่รู้ว่า Linear Layout ที่เป็น Parent มีความกว้างเท่าไร
ในกรณีนี้เราสามารถใช้ Layout Weight แล้วกำหนดค่าให้กับ Child View ทุกตัวให้มีค่าเท่ากันได้เลย แล้วเดี๋ยว Linear Layout จะจัดให้ Child View ทุกตัวมีความกว้างเท่ากันทันที
โดยค่า Weight ที่กำหนดไว้ใน Child View แต่ละตัว Linear Layout จะนำมารวมกันเป็น Weight Sum แล้วดูว่าค่า Weigh แต่ละตัวคิดเป็นกี่เปอร์เซ็นต์ของ Weight จึงทำให้วิธีนี้ยืดหยุ่นกว่าการกำหนดค่าเป็นเปอร์เซ็นต์โดยตรง
เพราะการกำหนด 33% จะใช้ได้เฉพาะ Child View 3 ตัวเท่านั้น แต่การกำหนดค่าเป็น Weight จะไม่สนใจว่า Child View มีอยู่ทั้งหมดกี่ตัว แต่ทุกตัวจะคำนวณออกมาได้เป็นเปอร์เซ็นต์ที่เท่ากันทั้งหมด
รูปแบบการทำงานของ Layout Weight
เพื่อให้ใช้งาน Layout Weight ได้อย่างถูกต้องและมีประสิทธิภาพ ควรรู้ก่อนว่า Layout Weight มีเงื่อนไขอะไรบ้าง และมีรูปแบบในการทำงานยังไง
Layout Weight ทำงานตาม Orientation ของ Linear Layout
การกำหนด Layout Weight จะมีผลต่อ Width หรือ Height ของ Child View จะขึ้นอยู่กับ Orientation ของ Linear Layout
- Orientation เป็น Vertical : Layout Weight จะมีผลกับ Height ของ Child View ส่วน Width จะกำหนดค่าเป็นอะไรก็ได้
- Orientation เป็น Horizontal : Layout Weight จะมีผลกับ Width ของ Child View ส่วน Height จะกำหนดค่าเป็นอะไรก็ได้
Layout Weight ไม่มีผลกับ Match Parent
จะมีผลกับค่าที่กำหนดแบบ Exact Dimension อย่างหน่วย dp หรือการใช้ Wrap Content ใน Child View ที่มี Content อยู่ข้างในเท่านั้น แต่ทางที่ดีแนะนำให้กำหนดค่าเป็น 0dp ดีกว่า เพราะมีผลต่อ Perfermance ของ UI Rendering และเพื่อไม่ให้สับสนกับ Child View ตัวอื่น ๆ ที่ไม่ได้กำหนดค่า Layout Weight
มีผลเฉพาะ Child View ที่กำหนด Layout Weight ด้วยกันเท่านั้น
ถ้ามี Child View ตัวอื่นที่ไม่ได้กำหนด Layout Weight อยู่ในนั้นด้วย จะคิดเฉพาะพื้นที่ที่เหลืออยู่เท่านั้น
และอย่างที่บอกไปก่อนหน้านี้ Child View ที่กำหนด Layout Weight ให้กำหนด Dimension เป็น 0dp ไปเลย เพื่อไม่ให้สับสนกับ Child View ตัวอื่น ๆ
Weight Sum จะคิดตามค่า Layout Weight ที่กำหนดไว้ในแต่ละตัว
จากตัวอย่างก่อนหน้านี้ทั้งหมด เจ้าของบล็อกจะใช้ค่าเป็น 1 ทั้งหมด แต่ในความเป็นจริงนั้น นักพัฒนาสามารถกำหนดค่า Weight เท่าไรก็ได้ เพราะ Linear Layout จะเอาผลรวมของ Weight ทั้งหมดมาคิดเป็น Weight Sum แล้วคำนวณอีกทีว่า Child View แต่ละตัวมีขนาดกี่เปอร์เซ็นต์ของ Weight Sum
ยกตัวอย่างเช่น นักพัฒนาสามารถแบ่ง Child View 2 ตัวให้มีขนาดเป็น 2 ต่อ 1 (66.66% และ 33.33%) แบบนี้ก็ได้
และอย่างที่บอกไปก่อนหน้านี้ว่า ถ้ามี Child View ตัวอื่นอยู่ด้วย แต่ไม่ได้กำหนด Layout Weight ก็จะคิดเฉพาะพื้นที่ที่เหลืออยู่เท่านั้น
กำหนด Weight Sum ให้กับ Linear Layout โดยตรงก็ได้
ปกติแล้ว Weight Sum จะคิดผลรวมจาก Layout Weight ที่กำหนดไว้ใน Child View แต่ถ้ากำหนด Weight Sum ไว้ที่ Linear Layout ก็จะใช้ค่านั้นมาคำนวณแทน
เหมาะกับ Child View ที่ต้องการให้มีขนาดเท่ากับพื้นที่ที่เหลืออยู่ใน Linear Layout
ถึงแม้ว่านักพัฒนาจะใช้ Match Parent เพื่อกำหนดให้ Child View ขยายขนาดจนเต็มพื้นที่ของ Parent แบบนี้ได้
แต่การทำงานของ Match Parent จะเป็นลักษณะ "ขยายไปด้านขวา" หรือ "ขยายไปด้านล่าง" จนสุดขอบของ Parent จึงทำให้การใช้ Match Parent ดัน Child View ตัวอื่นให้ล้นออกไปจาก Parent ได้ ถ้า Child View ตัวนั้นอยู่ลำดับถัดไป
ด้วยเหตุนี้จึงทำให้การใช้ Layout Weight ตอบโจทย์กับ UI ในลักษณะแบบนี้กว่า เพราะจะคำนวณจากพื้นที่ที่เหลืออยู่ใน Parent เท่านั้น ทำให้ Child View ในลำดับถัดไปยังคงอยู่ในพื้นที่ของ Parent อยู่
วิธีการใช้งาน
การใช้ Layout Weight สามารถกำหนดได้ทั้งใน Layout Resource (XML) และ LinearLayout.LayoutParams (Java/Kotlin) ก็ได้ แต่แนะนำให้กำหนดไว้ใน Layout Resource (XML) ดีกว่า
โดยกำหนดด้วย XML Attribute ที่ชื่อว่า android:layout_weight
แบบนี้
<LinearLayout
android:orientation="horizontal"
...>
<ImageView ... />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
... />
</LinearLayout>
ในกรณีที่ต้องการกำหนด Weight Sum ไว้ใน Linear Layout เลย ก็ให้ใช้ XML Attribute ที่ชื่อว่า android:weightSum
<LinearLayout
android:orientation="horizontal"
android:weightSum="2"
...>
<ImageView ... />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
... />
</LinearLayout>
เพียงเท่านี้ก็จะได้ UI ที่ทำงานตามค่า Layout Weigth ที่กำหนดไว้ทั้งใน LinearLayout และ TextView แล้ว
คำสั่งของ Layout Weight จะเรียบง่ายมาก แต่สิ่งสำคัญที่สุดคือหลักการทำงานของ Layout Weight เพื่อให้นักพัฒนาสามารถนำไปใช้งานในรูปแบบต่าง ๆ ได้อย่างมีประสิทธิภาพ
สรุป
Layout Weight เป็นหนึ่งใน Attribute เฉพาะของ Linear Layout ที่ช่วยให้นักพัฒนาสามารถกำหนดขนาดของ Child View ได้ยืดหยุ่นและตอบโจทย์กับความต้องการได้ง่ายขึ้น โดยใช้การแบ่งสัดส่วนพื้นที่ที่เหลืออยู่ใน Linear Layout แล้วแบ่งเป็นเปอร์เซ็นต์ตามค่า Weight ที่กำหนดไว้ใน Child View แต่ละตัว จึงทำให้การใช้ Layout Weight ตอบโจทย์ในบางรูปแบบที่ไม่สามารถใช้ Match Parent หรือกำหนดค่าเป็น Exact Dimension ได้
และนอกจากนี้รูปแบบการทำงานของ Layout Weight ใน Linear Layout นี้ก็ถูกนำไปใช้ใน layout_constraintHorizontal_weight
กับ layout_constraintVertical_weight
ของ Constraint Layout เวลาทำ Chain ระหว่าง Child View ด้วยนะ