25 มิถุนายน 2555

[Android Design] การกำหนดขนาดใน Properties



        ข้อมูลในการออกแบบแอพพลิเคชันบนแอนดรอยด์ เจ้าของบล็อกจะอ้างอิงข้อมูลจาก Android Developer หรือจะบอกว่าแปลเป็นภาษาไทยให้ฟังก็ได้ แต่เนื้อหาไม่ได้เอามาแปลทั้งหมดนะ จะเปลียนแปลงตามความเหมาะสมแทน

       สำหรับขนาดบนแอนดรอยด์จะมีหน่วยต่างๆดังนี้

Pixels (px)
        เป็นหน่วยที่ขึ้นอยู่กับจำนวน Pixels ของหน้าจอ ซึ่งไม่ขอยกตัวอย่างอะไรมาก เพราะรู้จักกันอยู่แล้ว ซึ่งอุปกรณ์แอนดรอยด์ ก็จะมีขนาดหน้าจอที่แตกต่างกันออกไป อย่างเช่น 320 x 240 (QVGA), 480 x 320 (HVGA), 800 x 480 (WVGA)

Inches (in)
        เป็นหน่วยที่ขึ้นอยู่กับขนาดของหน้าจอในหน่วยนิ้ว

Millimeters (mm) 
        เป็นหน่วยที่ขึ้นอยู่กับขนาดของหน้าจอในหน่วยมิลลิเมตร

Points (pt)
        เป็นหน่วยที่ขึ้นอยู่กับขนาดของหน้าจอในหน่วย 1/72 นิ้ว

Density-independent Pixels (dp)
        เป็นหน่วยสมมติขึ้นมาโดยอ้างอิงจากขนาดหน้าจอและความหนาแน่นของหน้าจอ โดยค่าดังกล่าวนี้จะทำให้อุปกรณ์แอนดรอยด์ที่มีขนาดหน้าจอต่างกัน มีค่าที่ใกล้เคียงกัน ศึกษาเพิ่มเติมได้ที่ [Android Design] แท้จริงแล้วหน่วย dp คืออะไร?

Scale-independent Pixels (sp)
        จะเหมือนกับ dp แต่สามารถกำหนดขนาดจากขนาดของฟอนต์ที่ผู้ใช้กำหนดไว้ได้ ซึ่งเหมาะที่จะใช้ตัวหนังสือ เพราะสามารถกำหนดจากความหนาแน่นของหน้าจอหรือจะกำหนดจากขนาดฟอนต์บนแอนดรอยด์ของผู้ใช้ก็ได้

        แหล่งข้อมูลเพิ่มเติม - Android Developer - Dimension

        สำหรับการออกแบบแอพพลิเคชัน เจ้าของบล็อกแนะนำให้ใช้หน่วย dp หรือ sp เป็นหลัก เพื่อให้แอพพลิเคชันมีขนาดพอดีกับทุกๆขนาดหน้าจอ เพราะหน่วย dp และ sp สามารถเปลี่ยนแปลงตามขนาดหน้าจอได้ ถ้าใช้หน่วยจำพวก px, in, pt หรือ mm ถ้าเปิดบนอุปกรณ์แอนดรอยด์ที่มีขนาดหน้าจอต่างกัน จะทำให้แอพพลิเคชันมีขนาดไม่พอดีกับหน้าจอ

        ตัวอย่างการใช้หน่วยจำพวก px, in,pt หรือ mm จะเห็นว่าเมื่อแสดงบนหน้าจอที่มีความละเอียดต่างกัน Widget ต่างๆในแอพพลิเคชัน จะมีขนาดแตกต่างกันด้วย



        ถ้าใช้หน่วยเป็น dp หรือ sp จะทำให้มีอัตราส่วนพอดีกับหน้าจอ แอพพลิเคชันจึงมีขนาดพอดีกับหน้าจอตลอดไม่ว่าจะมีความละเอียดเท่าไรก็ตาม



        และนอกจากการกำหนดเป็นหน่วยแล้วยังกำหนดโดยสัมพันธ์กับ View ได้ดังนี้

wrap_content
        เป็นการกำหนดขนาดให้พอดีกับภายใน Widget โดยขึ้นอยู่กับขนาดของ Properties ที่อยู่ใน Widget นั้นๆ หรือ Widget อื่นๆที่อยู่ใน Widget นั้นๆอีกทีนึง ถ้ายังงงๆ ก็ลองดูรูปประกอบข้างล่างนี้ละกัน


        จะเห็นว่า Button ทั้งสองมีขนาดต่างกัน แต่เจ้าของบล็อกกำหนดเป็น wrap_content ทั้งคู่ ที่มีขนาดต่างกันเพราะว่าปุ่มทั้งสองมีข้อความต่างกัน ความยาวของตัวอักษรจึงแตกต่างกัน ดังนั้นปุ่มจึงมีขนาดแตกต่างกันเพราะ wrap_content จะปรับขนาดให้พอดีกับ Properties ไม่ว่าจะเป็นข้อความใน Widget หรือภาพพื้นหลัง

fill_parent 
        เป็นการกำหนดขนาดให้พอดีกับขนาดของหน้าจอ ไม่ว่าจะเป็นแอนดรอยด์ที่มีขนาดหน้าจอต่างกัน ก็จะมีขนาดเท่ากับขนาดหน้าจอ ไม่ได้หมายความว่าจะเต็มหน้าจอทั้งหมดนะ เพราะจะขึ้นอยู่กับว่ากำหนดใน Width หรือ Height อย่างเช่น ให้ Width เป็น fill_parent ก็จะมีความกว้างเท่ากับความกว้างของจอ ส่วนความสูงก็กำหนดอีกที

match_parent
        เหมือนกับ fill_parent ซึ่งก็คือ fill_parent แหละ แต่ได้เปลี่ยนมาใช้เป็น match_parent ใน API 8 ดังนั้นใน API ต่ำกว่า 8 จะใช้ match_parent ไม่ได้

        แหล่งข้อมูลเพิ่มเติม - Android Developer - Layout Parameter

        ทีนี้ลองมาดูตัวอย่างตอนใช้งานจริงดีกว่า เพราะว่า fill_parent หรือ match_parent ก็ใช่ว่าต้องมีขนาดพอดีกับหน้าจอเสมอไป เพราะขึ้นอยู่กับตำแหน่งของ Widget นั้นๆด้วย

        เจ้าของบล็อกจะใช้คำสั่งนี้เป็นตัวอย่างให้ผู้ที่หลงเข้ามาอ่านเอาไปแปะใน xml เลย
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#37ACD8" >
    <LinearLayout
        android:id="@+id/LinearLayout2"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="Button 1" />
        <LinearLayout
            android:id="@+id/LinearLayout3"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >
            <Button
                android:id="@+id/button2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Button 2" />
            <Button
                android:id="@+id/button3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Button 3" />
            <Button
                android:id="@+id/button4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Button 4" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

        เมื่อดูในหน้าต่าง Graphical Layout จะได้ลักษณะดังนี้



        เจ้าของบล็อกจะขอพูดถึง LinearLayout ก่อน เพราะการจะวาง Button ลักษณะแบบนี้ได้ ที่แน่ๆเลยก็คือต้องมี LinearLayout มารองรับก่อน ซึ่งใช้ LinearLayout แบบ Horizontal และ Vertical โดยเจ้าของบล็อกจะวางแบบนี้ (ดูจากในคำสั่ง)


    LinearLayout จะมี Height และ Width เป็น match_parent 
    (ความกว้างและความยาวพอดีกับหน้าจอ)

    LinearLayout2 มี Height เป็น match_parent และ Width เป็น wrap_content 
    (ความกว้างเท่ากับ Widget และความยาวพอดีกับหน้าจอ)

    LinearLayout3 มี Height เป็น match_parent และ Width เป็น match_parent
    (ความกว้างและความยาวพอดีกับหน้าจอ)
        โดย LinearLayout2 และ LinearLayout3 อยู่ใน LinearLayout1 ดังนั้น LinearLayout1 ก็จะมีขนาดพอดีกับหน้าจอจริงๆ แต่ทำไม LinearLayout3 ที่กำหนดขนาดเหมือนกับ LinearLayout1 ถึงไม่พอดีกับหน้าจอเหมือนกันล่ะ?

        เพราะการวางตำแหน่งของ Widget ในแอนดรอยด์จะมีจุดอ้างอิงเริ่มต้นที่ตรงมุมซ้ายบนทุกครั้ง ซึ่งจริงๆแล้วการกำหนดเป็น match_parent จะเป็๋นการขยายขนาดไปทางข้างล่างหรือทางขวาเท่านั้น ไม่ได้หมายความว่าขยายให้เต็มจอโดยสิ้นเชิง ดังนั้นถ้าวาง Widget อื่นๆตรงซ้ายมือหรือด้านบนของ Widget นั้นๆ ก็จะไม่โดนเบียดแต่อย่างใด Widget นั้นๆก็จะขยายๆไปด้านซ้ายและข้างล่างแทน ถ้าผู้ที่หลงเข้ามาอ่านยังงงๆ ลองดูรูปประกอบละกัน โดย match_parent จะขยายขนาดไปตามทิศทางลูกศร



        และ wrap_content ก็จะประมาณนี้



        ซึ่งจริงๆแล้ว จะมองไม่เห็นขอบเขตเป็นแบบนี้หรอก เจ้าของบล็อกสมมติภาพขึ้นมาเพื่อให้เข้าใจง่าย โดยจริงๆแล้ว LinearLayout2 และ LinearLayout3 จะทับกับ LinearLayout1 พอดี และ LinearLayout2 ก็จะมองไม่เห็น ถ้าไม่มี Widget อยู่ภายใน เพราะมีความกว้างเป็น wrap_content ดังนั้นจะมีขนาดพอดีกับ Widget ภายในเท่านั้น ถ้าภายใน LinearLayout2 ไม่มี Widget ก็จะมีความกว้างเป็น 0 แทน และสำหรับ Button ก็เหมือนๆกันนั่นแหละ รูปประกอบก็จะเป็นดังนี้




        แต่ในทางกลับกัน ถ้า Widget อื่นๆอยู่ทางขวามือหรือด้านล่าง Widget อื่นๆก็จะโดนเบียดออกนอกหน้าจอไปนั่นเอง ซึ่งในคำสั่งตัวอย่างในข้างบนนี้ จะเห็นว่ามี Button4 อยู่ด้วย ซึ่งอยู่ต่อท้ายจาก Button3 ที่มี Width และ Height เป็น match_parent ก็จะโดนเบียดออกนอกหน้าจอไป



 
      ซึ่งสามารถใช้ ScrollView เพื่อเลื่อนหน้าขึ้น-ลงหรือซ้าย-ขวาก็ได้ เพราะบางทีก็ไม่จำเป็นต้องแสดงทุกอย่างทั้งหมดในหน้าจอ จะให้ผู้ใช้เลื่อนไปด้านข้างเพื่อดูต่อก็ได้




เหล่าพันธมิตรแอนดรอยด์

Devahoy Layer Net NuuNeoI The Cheese Factory Somkiat CC Mart Routine Artit-K Arnondora Kamonway Try to be android developer Oatrice Benz Nest Studios Kotchaphan@Medium Jirawatee@Medium Travispea@Medium