24 November 2012

Layout Weight ใช้อย่างไร ใช้ให้เป็น

Updated on


        บทความรอบนี้ก็ขอพูดถึงเรื่องที่มองข้ามกันอยู่บ่อยๆเสียหน่อย นั่นก็คือเรื่อง Layout Weight หรือใน xml คือ android:layout_weight ซึ่งเจ้าคุณสมบัติดังกล่าวเชื่อว่าผู้ที่หลงมาอ่านหลายคนไม่รู้ว่ามันคืออะไร มีคุณสมบัติอย่างไร และใช้งานยังไง เจ้าของบล็อกก็เลยขอหยิบมาพูดถึงบ้างหน่อยดีกว่า

        เพราะว่าเจ้า Properties ตัวนี้มีความสำคัญค่อนข้างมากในเวลาที่ออกแบบหน้าตาแอปพลิเคชันหรือตอนที่จัด Layout นั่นเอง

        สำหรับคุณสมบัติ layout_weight จะมีใน View และ Layout เกือบทุกตัว โดยที่การใช้งานคุณสมบัติ layout_weight จะมีไว้ใช้กับ View หรือ Layout ที่วางอยู่ภายใน Linear Layout เท่านั้น ถ้าใช้ Layout อื่นๆเช่น Relative Layout พวก View ที่อยู่ข้างในก็จะไม่มี Properties ตัวนี้ให้กำหนด

        ดังนั้นก็ขึ้นอยู่กับแต่ละงานของผู้ที่หลงเข้ามาอ่านว่ามีความจำเป็นต้องใช้ Linear Layout หรือป่าว เพราะบางที Relative Layout ก็เหมาะกับการบางงานมากกว่า และบางงานการใช้ Linear Layout ก็อาจจะเหมาะกว่า



        ทีนี้ขออธิบายเจ้าคุณสมบัติ layout_weight กันต่อเลย ซึ่งคุณสมบัตินี้มีไว้กำหนดขนาดของ View หรือ Layout ให้มีอัตราส่วนแน่นอน โดยอัตราส่วนที่ว่าจะมีผลเฉพาะ View หรือ Layout ที่กำหนดค่า layout_weight เท่านั้น จะไม่มีการคิดอัตราส่วนจากตัวที่ไม่ได้กำหนดค่า layout_weight

        เพิ่มเติม - สำหรับทิศทางของ Weight จะขึ้นอยู่กับ Linear Layout ว่ามี Orientation ไปในทิศทางใด ถ้าเป็น Horizontal จะกำหนดเป็นค่าความกว้าง (Width) และถ้าเป็น Vertical ก็กำหนดเป็นค่าความสูง (Height) แทน


        การคิดอัตราส่วนง่ายๆเลย สมมติว่าเจ้าของบล็อกสร้าง Edit Text ขึ้นมา แล้วก็ทำการกำหนดให้ layout_width เป็น 0dp ก่อน เพื่อไม่ให้ค่าช่องนี้มารบกวน แล้วกำหนดให้ layout_weight มีค่าเท่ากับ 1 ก็จะเห็นว่า Edit Text ขยายสุดขอบ

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:background="#f9443f"  
    android:gravity="center" >  
    <requestFocus />  
    <EditText  
        android:id="@+id/editText1"  
        android:layout_width="0dp"  
        android:layout_height="wrap_content"  
        android:layout_weight="1"  
        android:hint="1" />  
</LinearLayout>  



        จากภาพข้างบนนี้ก็จะเห็นว่าเจ้าของบล็อกกำหนดให้ Weight เป็น 1 และในแถวเดียวกันก็มีแค่ Edit Text อยู่อันเดียว Weight รวมจึงเป็น 1 เช่นกัน จึงได้อัตราส่วน 1 : 1 หรือก็คือ Edit Text จะขยายความกว้างจนเต็มขอบพอดี

        รู้นะว่ายังงงๆอยู่.. แต่ไม่เป็นไร เพราะเจ้าของบล็อกเตรียมไว้หลายภาพไว้แล้ว จะได้เสริมความเข้าใจให้มากขึ้น

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f9443f"
    android:gravity="center" >
    <requestFocus />
    <EditText
        android:id="@+id/editText1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="1" />
    <EditText
        android:id="@+id/editText2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="2" />
</LinearLayout>



        ตัวอย่างต่อมาจะเห็นว่าเจ้าของบล็อกสร้าง Edit Text มาสองอัน โดยกำหนดแต่ละอันให้มี Weight เท่ากับ 1 ดังนั้น Weight รวมจะเป็น 2 ผลที่ได้ก็คือ Edit Text ทั้งสองอันก็จะมีขนาดอย่างละครึ่งของหน้าจอ


        ตามด้วยตัวอย่างต่อไปเลย!
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f9443f"
    android:gravity="center" >
    <requestFocus />
    <EditText
        android:id="@+id/editText1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="4"
        android:hint="1" />
    <EditText
        android:id="@+id/editText2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="2" />
</LinearLayout>



        จะเห็นว่าเจ้าของบล็อกกำหนด Edit Text เบอร์หนึ่งให้มี Weight เป็น 4 และเบอร์สองมี Weight เป็น 1 ดังนั้น Weight รวมจึงเป็น 5 แต่ว่าเบอร์หนึ่งจะมีขนาด 4 : 5 และเบอร์สองมีขนาดเป็น 1 : 5 จึงเห็นว่าเบอร์หนึ่งมีขนาดใหญ่กว่าเบอร์สองอยู่ 4 เท่า


        อ๊ะ อ๊ะ!! เริ่มเข้าใจขึ้นมาบ้างแล้วละสิ ต่อเลยละกัน
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f9443f"
    android:gravity="center"
    android:orientation="horizontal" >
    <requestFocus />
    <EditText
        android:id="@+id/editText1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="1" />
    <EditText
        android:id="@+id/editText2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:hint="2" />
    <EditText
        android:id="@+id/editText3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:hint="3" />
</LinearLayout>



        ทีนี้เจ้าของบล็อกสร้างขึ้นมาสามอันเลย โดยเบอร์ 1, 2 และ 3 มีค่า Weight เท่ากับ 1, 2 และ 3 ตามละดับ ก็จะเห็นว่า Weight รวมเป็น 6 โดยเบอร์หนึ่งมีขนาด 1 : 6 ส่วนเบอร์สองมีขนาด 2 : 6 และเบอร์สามมีขนาด 3 : 6


        ถึงตอนนี้แล้ว ผู้ที่หลงเข้ามาอ่านก็คงเข้าใจการใช้ layout_weight แล้วละมั้ง
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f9443f"
    android:gravity="center"
    android:orientation="vertical" >
    <Button
        android:id="@+id/editText1"
        android:layout_width="50dp"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:hint="1" />

    <Button
        android:id="@+id/editText2"
        android:layout_width="50dp"
        android:layout_height="0dp"
        android:layout_weight="7"
        android:hint="2" />

    <Button
        android:id="@+id/editText3"
        android:layout_width="50dp"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:hint="3" />
</LinearLayout>



        จะกำหนดเป็นแนวตั้งก็แค่เปลี่ยน Orientation ของ Lineat Layout ให้เป็น Vertical เวลากำหนดค่า Weight ก็จะเป็นการกำหนดความสูงแทน ดังนั้นเจ้าของบล็อกจึงกำหนดให้ layout_height เป็น match_perent แทน และ layout_width เป็น 0dp โดยอันนี้จะใช้เป็น Button แทน Edit Text แล้ว เพื่อให้ดูเป็นตัวอย่างก็จะเห็นว่า Weight รวมเป็น 9 เบอร์หนึ่ง 1 : 9, เบอร์สอง 7 : 9 และเบอร์สาม 1 : 9


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f9443f"
    android:orientation="horizontal" >
    <Button
        android:id="@+id/editText1"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:hint="1" />
    <Button
        android:id="@+id/editText2"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="5"
        android:hint="2" />
</LinearLayout>


        กรณีนี้จะเห็นว่าเจ้าของบล็อกกหนดความสูงให้เป็น match_parent เพื่อจำลองการแบ่งช่องบนหน้าจอแสดงผล โดยสมมติว่าช่องซ้ายมือเป็นช่องสำหรับเมนูตัวเลือกต่างๆ และช่องขวามือเป็นหน้าหลัก

        มาถึงตัวอย่างสุดท้ายล่ะ เจ้าของบล็อกไม่อยากให้ผู้ที่หลงเข้ามาอ่านเข้าใจผิดว่าถ้ามีการใช้ Weight ก็ต้องมีการกำหนดทั้งหมดตลอด ซึ่งมันไม่จำเป็น อันไหนที่ไม่ได้กำหนดก็ไม่นำมาคิด Weight รวม คิดอันที่กำหนดค่า Weight เท่านั้น
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f9443f"
    android:gravity="bottom" >
    <requestFocus />
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />
    <EditText
        android:id="@+id/editText1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="1" />
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />
    <EditText
        android:id="@+id/editText2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:hint="2" />
</LinearLayout>



        ภาพสุดท้ายนี้จะเห็นว่าเจ้าของบล็อกเพิ่ม Button เข้าไปสองปุ่มและ Edit Text อีกสองช่อง โดยที่ Button ไม่ได้กำหนดค่า Weight จะกำหนดเฉพาะ Edit Text เท่านั้น ดังนั้นขนาดของ Button ก็จะไม่เปลี่ยนแปลงไปตามอัตราส่วนของจอ กำหนดไว้เท่าไรก็เท่านั้น แต่ Edit Text ก็จะยังคงเปลี่ยนแปลงไปตามอัตราส่วนอยู่เหมือนเดิม โดยคิด Weight แค่ Edit Text เท่านั้น เป็น 3 โดยจะไม่รวมส่วนที่เป็นปุ่มหรือก็คือคิด Weight ขนาดเท่าไรก็แบ่งเป็นอัตราส่วนตามขนาดที่เหลือ ดังนั้นเบอร์หนึ่งก็จะมีขนาดเป็น 1 : 3 และเบอร์สองมีขนาด 2 : 3

        รูปสุดท้ายเจ้าของบล็อกตั้งใจสื่อให้เห็นว่า การใช้ Weight ไม่จำเป็นต้องบ้าจี้ กำหนดค่า Weight ไปซะทุกอัน เพียงแต่ว่ากำหนดเฉพาะอันที่จำเป็นก็พอ อย่างพวก Button ที่ไม่ต้องการเปลี่ยนแปลงความกว้างตามหน้าจอก็ช่างมัน มักจะใช้กับ Edit Text มากกว่า เพื่อให้มีช่องกรอกข้อความกว้างตามขนาดหน้าจอ


        ขอฝากทิ้งท้ายก่อนจะจบบทความละกันว่าทำไมเจ้าของบล็อกถึงกำหนดขนาดของด้านที่จะใช้ร่วมกับ layout_weight เป็น 0dp เช่น Vertical จะใช้ layout_height เป็น 0dp เป็นต้น ทำไมถึงไม่ใช่เป็น match_parent ซะเลยล่ะ?


        ภาพข้างบนนี้จะเห็นว่าถ้ากำหนดเป็น 0dp ขนาดก็จะเป็นไปตามที่ได้อธิบายไว้ แต่ทว่าพอกำหนดเป็น match_parent กลับกลายเป็นว่าอัตราส่วนของขนาดสลับกันซะงั้น กลายเป็นว่า 2 มีขนาดใหญ่กว่า และ 3 มีขนาดเล็กกว่า ดังนั้นเพื่อไม่ให้สับสนจังแนะนำให้ใช้เป็น 0dp แทนจะดีกว่า (เพราะถ้าใช้ match_parent ในโค๊ดก็จะมีการแจ้งเตือนอยู่ดีว่าแนะนำให้ใช้ 0dp แทน)


        ก็หมดแล้วล่ะสำหรับตัวอย่างที่เจ้าของบล็อกเอามาให้ดู หวังว่าน่าจะเข้าใจการใช้ layout_weight กันบ้างแล้วนะ สำหรับใครที่ต้องการไฟล์ layout ในตัวอย่างของบทความนี้สามารถดาวน์โหลดได้ที่ Layout Weight [Google Drive] หรือ Layout Weight [GitHub]

        สำหรับไฟล์ตัวอย่างให้ดูที่ res/layout อย่างเดียวนะ สร้างไว้เป็นไฟล์ ex_1.xml จนถึง ex_7.xml อย่างอื่นไม่ต้องสน


        ไว้จะทำบทความแนวๆนี้ให้เรื่อยๆนะ