Linear, Relative, Constraint, Table, Frame และอื่นๆ อีกมากมาย Android มี Layout ให้เลือกมากมายเมื่อต้องการออกแบบแอปพลิเคชัน คำถามคือ: อันไหนดีที่สุด?
ก่อนจะรายละเอียดแต่ละ Layout เราจะกล่าวถึง View Object Hierarchy และกระบวนการวาดของ Android ก่อน
View และ ViewGroup
คิดว่า ViewGroup เป็น Parent Class ของ View ทุกตัว และเป็น Base Class สำหรับ Layouts มันคือ Container ที่บรรจุ Views อื่นๆ เช่น LinearLayout เป็น ViewGroup เพราะสามารถบรรจุ Views และ Layouts อื่นได้
ส่วน View เป็นองค์ประกอบพื้นฐานของ UI Elements Views สามารถเป็นส่วนหนึ่งของ ViewGroup ได้ เช่น TextView เป็น View
Measure → Layout → Draw → Repeat
Layouts ถูกบันทึกเป็นไฟล์ XML ใน Android แล้วมันกลายเป็น Object บนหน้าจออย่างไร? แต่ละ XML จะถูก Instantiate (inflate) และสร้าง View Hierarchy Tree หาก Layout B นั่งซ้อนใน Layout A จะมีความสัมพันธ์ Child-Parent (Layout A เป็น Parent ของ Layout B) เมื่อ Tree สร้างเสร็จ จะมี 3 Phase:
Measure
Phase แรก แต่ละ Parent Node คำนวณ Constraints เกี่ยวกับขนาดของ Children ส่งข้อจำกัดลงไปให้ Children แต่ละตัวประเมินขนาดตัวเอง (อยากใหญ่แค่ไหน) พร้อมพิจารณาข้อจำกัดที่ได้รับและของ Children
Layout
แต่ละ Node 决定ขนาดและตำแหน่งสุดท้ายของ Children บนหน้าจอ
Draw
เริ่มจาก Root Node วาดตัวเอง แล้วสั่ง Children วาดทับกันไปเรื่อยๆ Parent วาดก่อน Children วาดทับด้านบน
เก็บกระบวนการข้างต้นไว้ในใจ ควรทำให้ Layout ของแอปเพี้ยนที่สุดเท่าที่จะเป็นไปได้ เพื่อลดเวลาในการ Traverse View Hierarchy
รายละเอียด Layouts
LinearLayout
จัดเรียง Children เป็นแถว แนวตั้งหรือแนวนอน (android:orientation) ทุก View จะอยู่ในแถวเดียวหรือคอลัมน์เดียว
คุณสมบัติน่าสนใจคือ layout_weight ใช้บอก LinearLayout ว่าแบ่งพื้นที่ให้ Child Views อย่างไร เหมาะสำหรับ Layout ที่สม่ำเสมอทั่วอุปกรณ์และทิศทาง
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="World!" />
</LinearLayout>
ถ้าต้องการ TextView แรก ("Hello") ใช้พื้นที่ 3/4 ของความกว้างหน้าจอ ใช้ layout_weight:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="4"
tools:context=".MainActivity">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="3"
android:text="Hello" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="World!"
android:layout_weight="1" />
</LinearLayout>
RelativeLayout
จัดตำแหน่ง Child Views แบบ Relative สามารถทำให้ Hierarchy เพี้ยน ไม่ต้องซ้อน ViewGroups แต่แต่ละ RelativeLayout ต้อง Measure 2 รอบ อาจส่งผลต่อ Performance
คุณสมบัติที่ใช้บ่อย: centerInParent ให้ Child อยู่กลาง Parent
ConstraintLayout
Constraint คือการเชื่อมต่อหรือจัดตำแหน่ง相对กับ Element อื่น กำหนด Constraints ให้ Child Views ทุกตัว สร้าง Layout ซับซ้อนได้พร้อม Hierarchy เพี้ยน (ไม่ซ้อน ViewGroups) คล้าย RelativeLayout ต้อง Measure 2 รอบเช่นกัน
FrameLayout
ใช้บรรจุ Child View เพียงตัวเดียว บล็อก View อื่นๆ ขนาด Layout เท่ากับ Child ใหญ่สุด (มองเห็นหรือไม่ก็ตาม) บวก Padding
หลีกเลี่ยงการวางหลาย Child Views ใน FrameLayout จะยากที่จะไม่ให้ Overlap ควบคุมตำแหน่งด้วย layout_gravity
ListView / GridView
ใช้เมื่อต้องแสดงหลาย Items (เช่น เมนูร้านอาหาร) ListView = รายการคอลัมน์เดียวเลื่อนได้ GridView = ListView หลายคอลัมน์
สำคัญ: Views เป็น Dynamic สร้าง Runtime ต้องใช้ AdapterView เพื่อ Populate Items
TableLayout
คล้าย GridView จัด Children เป็น Rows และ Columns แต่ละ Layout มีหลาย TableRow แต่ละอันกำหนด Row
อย่ากลัวลอง Layout ต่างๆ จนเจอตัวที่เหมาะสมที่สุด รู้สึกสบายใจแบ่งปันในความคิดเห็นว่าชอบ Layout ไหนและเพราะอะไร