29 December 2017

แบ่ง Layout ให้รองรับหน้าจอทุกขนาดด้วย Configuration Qualifier กันเถอะ

Updated on


        เรื่อง Multiple Screen Support หรือการทำให้แอปฯรองรับกับหน้าจอทุกขนาดถือว่าเป็นหนึ่งในเรื่องพื้นฐานที่นักพัฒนาจะต้องทำให้ได้ เพราะมันคงจะดูตลกไม่น้อยถ้าต้องบอกกับผู้ใช้ว่าแอปฯของผู้ที่หลงเข้ามาอ่านรองรับกับหน้าจอบางขนาดเท่านั้น ดังนั้นบทความนี้เจ้าของบล็อกจึงขอแชร์หนึ่งในเทคนิคง่ายๆที่ทำให้แอปฯสามารถรองรับกับหน้าจอทุกขนาดด้วย Configuration Qualifier กัน

หัวใจสำคัญคือหน่วย DP

        ทุกวันนี้นักพัฒนาแอนดรอยด์ส่วนใหญ่รู้กันอยู่แล้วว่าเวลาออกแบบ Layout จะต้องกำหนดขนาดของ View หรือ Layout ด้วย dp เพราะว่าหน่วย dp จะเข้ามาช่วยแก้ปัญหาเรื่องหน้าจอหลายขนาดที่มี Resolution ในหน่วย px ที่ต่างกัน


        นั่นหมายความว่าถ้าหน้าจอที่มีขนาดใกล้เคียงกัน ต่อให้มี Resolution ที่ต่างกันมากเท่าไร เวลากำหนดเป็นหน่วย dp ก็จะได้ขนาดของ View หรือ Layout ที่ใกล้เคียงกัน ไม่เพี้ยนจนน่าเกลียด (ไม่ได้เท่ากันเป๊ะๆนะ)

แต่หน่วย DP ก็ยังมีปัญหากับหน้าจอหลายขนาดอยู่ดี

        ถึงแม้ว่าจะใช้หน่วย dp ในการออกแบบ Layout ก็ตาม แต่นั้นก็ไม่ได้หมายความว่า Layout นั้นๆจะรองรับกับหน้าจอทุกขนาดเสมอไป ตราบใดที่ผู้ที่หลงเข้ามาอ่านยังไม่รู้อะไรเกี่ยวกับขนาดหน้าจอของอุปกรณ์แอนดรอยด์ที่มีอยู่ในตลาดทุกวันนี้

        เมื่อผู้ที่หลงเข้ามาอ่านออกแบบ Layout ด้วยหน่วย DP นั่นหมายความว่าเวลามองขนาดหน้าจอของอุปกรณ์แอนดรอยด์จะต้องมองเป็นหน่วย DP ด้วยนะ ยกตัวอย่างเช่น ถ้าต้องการออกแบบ Layout ให้รองรับกับ Google Pixel จะต้องรู้ก่อนว่า Google Pixel มีขนาดหน้าจอในหน่วย dp เท่าไร


         และอุปกรณ์แอนดรอยด์ที่วางขายอยู่บนโลกนี้ก็จะมีขนาดหน้าจอในหน่วย dp แตกต่างกันไป ซึ่งจริงๆมันก็เยอะแหละ แต่ก็น้อยกว่าหน่วย px ซึ่งไม่ต้องบ้าจี้ไปนั่งหาหรือจำขนาดหน้าจอทั้งหมดหรอกนะ เพราะว่าเจ้าของบล็อกรวบรวมมาให้แล้ว


        จริงๆยังขาดอีก 2-3 ขนาด แต่ทว่าเท่านี้ก็เยอะพอแล้วล่ะ

        จะเห็นว่าโลกของความเป็นจริงนั้นค่อนข้างโหดร้ายพอสมควร เพราะว่าขนาดหน้าจอถึงแม้จะปัดเป็นหน่วย dp แล้ว มันก็ยังโคตรเยอะอยู่ดี

        แต่ถ้าดูดีๆก็จะพบว่าผู้ที่หลงเข้ามาอ่านสามารถจัดกลุ่มของขนาดหน้าจอที่ใกล้เคียงกันให้อยู่กลุ่มเดียวกันได้นะ โดยอ้างอิงจาก Smallest Width (sw) หรือก็คือด้านที่มีค่าน้อยที่สุด


        โดยเจ้าของบล็อกจะใช้เกณฑ์ในการจัดกลุ่มดังนี้

        • 1080dp
        • 720dp
        • 540dp
        • 480dp
        • 360dp
        • นอกเหนือจากนี้ถือว่าเป็น Default


        จะเห็นว่าด้วยวิธีนี้จะทำให้ขนาดหน้าจอในหน่วย dp เหลืออยู่แค่ 6 กลุ่มเท่านั้น และยังสามารถตัดออกได้อีก 2 กลุ่มคือ 480dp และ 1080dp เนื่องจากขนาดหน้าจอใน 2 กลุ่มนี้เป็นเฉพาะบางเครื่องเท่านั้น เมื่อคิดสัดส่วนที่มีทั้งหมดแล้วถือว่าน้อยมากกกกกกก ยกตัวอย่างเช่น หน้าจอขนาด 1,920x1,080 dp จะมีแค่ Samsung Galaxy View รุ่นเดียวเท่านั้น แถมเป็นรุ่นที่ไม่ค่อยนิยมด้วย


        ดังนั้นเจ้าของบล็อกจึงตัดออกเหลือแค่ 4 กลุ่มแทน


        โดยการแบ่งกลุ่มด้วยเลขดังกล่าวไม่ได้มโนขึ้นมาแบบมั่วซั่วนะ แต่จะอิงกับประเภทของอุปกรณ์แอนดรอยด์ด้วย

ใช้ Configuration Qualifier เพื่อแยก Resource สำหรับหน้าจอแต่ละขนาด

        ถ้าผู้ที่หลงเข้ามาอ่านอยากจะออกแบบหน้าจอสำหรับ Phone และ Tablet แยกกัน ก็ให้สร้าง Layout Resource แบบนี้

        • layout สำหรับ Phone
        • layout-sw540dp สำหรับ Tablet

        และถ้าอยากจะแยก Layout สำหรับ Tablet 7" กับ Tablet ที่ใหญ่กว่า 7" ขึ้นไป ก็สร้างเป็นแบบนี้

        • layout สำหรับ Phone
        • layout-sw540dp สำหรับ Tablet 7"
        • layout-sw720dp สำหรับ Tablet ที่ใหญ่กว่า 7"

        จะเห็นว่าการแบ่งระหว่าง Phone กับ Tablet ควรจะใช้ค่า 540dp เพราะว่ามีอุปกรณ์แอนดรอยด์ที่เป็น Tablet ขนาด 7" และอัตราส่วนหน้าจอเป็น 16:9 อยู่ จึงทำให้มีขนาดหน้าจอเป็น 960x540 dp ดังนั้นถ้าผู้ที่หลงเข้ามาอ่านคนไหนที่ใช้ 600dp ในการแบ่งระหว่าง Phone กับ Tablet ก็จะผิดทันที เพราะเวลาแอปฯทำงานบน Tablet ที่มีหน้าจอเป็น 960x540 dp ก็จะไปใช้ Layout ของ Phone แทน ทำให้ Layout ผิดเพี้ยนได้

         ในกรณีที่ใช้ Layout ร่วมกัน แต่แยก Dimension Resource ก็สามารถสร้าง dimens.xml แยกตามแต่ละขนาดหน้าจอได้เลย

        • values/dimens.xml
        • values-sw360dp/dimens.xml
        • values-sw540dp/dimens.xml
        • values-sw720dp/dimens.xml

        หรือจะแยกแค่ Phone กับ Tablet ก็ได้

        • values/dimens.xml
        • values-sw540dp/dimens.xml

        แต่เพื่อความชัวร์ แนะนำให้ทดสอบกับหน้าจอมือถือขนาดเล็กและ Tablet ขนาดใหญ่กว่า 7 นิ้วด้วย เพื่อดูว่า Layout เพี้ยนตรงไหนหรือไม่ ถ้ามีบางจุดที่เพี้ยน และจำเป็นต้องแยก Dimension ก็ให้สร้าง Dimension Resource ขึ้นมาแล้วกำหนดเฉพาะค่านั้นๆก็ได้

ใช้ประโยชน์จาก Smallest Width ในการออกแบบ Layout

        โดยปกติแล้ว ในการออกแบบ Layout ที่ดี ผู้ที่หลงเข้ามาอ่านควรกำหนดขนาดของ View หรือ Layout ให้มีความกว้างเป็น Match Parent เพื่อให้เต็มกับหน้าจอ ส่วนความสูงของหน้าจอก็ทำให้มันเลื่อนขึ้นลงได้ซะ


        แต่ในบางครั้งก็พบว่า Layout ที่ออกแบบไว้มันดูไม่น่าพิศมัยเวลาแสดงบนหน้าจอที่กว้างกว่าที่ออกแบบไว้ ลองใช้วิธีกำหนดขนาดของ View หรือ Layout ให้มีขนาดไม่เกินตามกลุ่มดูได้นะ

        ยกตัวอย่างเช่น Layout ในกลุ่มของ sw360dp ถ้าแสดงบนหน้าจอ 731x411 dp แล้วดูไม่สวย ก็ให้กำหนดความกว้างของ View หรือ Layout ให้ไม่เกิน 360dp ซะ


        เพียงเท่านี้ก็จะแก้ปัญหา View หรือ Layout ยืดยาวจนไม่สวยงามแล้ว โดยแลกกับด้านข้างของหน้าจอมีช่องไฟเล็กน้อย ซึ่งก็ไม่ถึงกับน่าเกลียด เพราะว่าเจ้าของบล็อกจัดกลุ่มให้แต่ละกลุ่มมี Smallest Width ที่ใกล้เคียงกันอยู่แล้ว

        • ถ้าเป็น sw720dp ก็ให้กำหนดความกว้างไม่เกิน 720dp
        • ถ้าเป็น sw540dp ก็ให้กำหนดความกว้างไม่เกิน 540dp
        • ถ้าเป้น sw360dp ก็ให้กำหนดความกว้างไม่เกิน 360dp
        • ถ้าเป็น default ก็ให้กำหนดความกว้างไม่เกิน 320dp

        ยกตัวอย่างเช่น

<!-- values/dimens.xml -->
<dimen name="content_width">300dp</dimen>

<!-- values-sw360dp/dimens.xml -->
<dimen name="content_width">340dp</dimen>

<!-- values-sw540dp/dimens.xml -->
<dimen name="content_width">500dp</dimen>

<!-- values-sw720dp/dimens.xml -->
<dimen name="content_width">660dp</dimen>

สรุป

        การใช้ Smallest Width หรือ sw มาช่วยในการแยก Layout สำหรับอุปกรณ์ประเภทต่างๆก็เป็นเทคนิคหนึ่งที่เจ้าของบล็อกใช้ประจำ เพราะเป็นวิธีรับมือกับหน้าจอขนาดต่างๆได้ค่อนข้างง่าย ขอแค่เข้าใจว่าขนาดหน้าจอของอุปกรณ์แอนดรอยด์มีกี่ขนาด ที่เหลือก็เป็นหน้าที่ของ Configuration Qualifier ที่จะช่วยแยกกลุ่มตามขนาดหน้าจอเหล่านี้ให้ แล้วผู้ที่หลงเข้ามาอ่านก็กำหนด Layout หรือ Dimension แยกตามขนาดหน้าจอได้เลย

        แต่วิธีนี้ก็เป็นแค่เพียงเทคนิคหนึ่งเท่านั้น ไม่เหมาะกับการออกแบบ Layout บางอย่าง ดังนั้นก็รับมือตามความเหมาะสมกันเองแล้วกันเนอะ