28 December 2014

แก้ปัญหาภาพพื้นหลังบิดเบี้ยวได้ง่ายๆด้วย Relative Layout

Updated on


       บทความนี้ว่าจะเขียนตั้งนานแล้ว แต่ว่าหาโอกาสไม่ได้ซักที (บ้างก็ลืม บ้างก็ไม่ว่าง)

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


        จะเห็นว่าภาพตัวอย่างข้างบนนี้พบได้ทั่วไปกับแอพฯที่ใช้วิธีเตรียมภาพที่มีขนาดหน้าจอพอดีกับเครื่องนั้นๆมาใช้ แต่เมื่อไปแสดงกับเครื่องที่มีอัตราส่วนหน้าจอที่ต่างกันออกไปก็จะทำให้ภาพที่ได้มีอัตราส่วนภาพเพี้ยนไป

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

        ซึ่งเจ้าของบล็อกเคยเขียนคลาสตัวหนึ่งเอาฮา เพื่อจัดการกับอัตราส่วนภาพที่จะแสดงเป็นภาพพื้นหลังโดยเฉพาะ

        แต่...มันใช้ไม่ได้หรอก

        เพราะว่ามันต้องจัดการด้วยโค๊ดอีกทีน่ะสิ นั่นก็หมายความว่ามันจะสิ้นเปลือง Resource โดยใช่เรื่อง และแอพฯทำงานช้าขึ้นด้วย!!!

        และปัญหานี้ก็แก้ได้ง่ายๆด้วยเทคนิคการจัดเลย์เอาท์ที่ไม่ยากเลย เพียงแค่ต้องใช้ไอเดียในการประยุกต์เสียหน่อยก็เท่านั้นเอง

        เจ้าของบล็อกเคยบอกกับผู้ที่หลงเข้ามาอ่านหลายๆคนเกี่ยวกับ Layout Designing อยู่ประจำว่า

        "ผู้ใช้รับรู้ตามที่มองเห็นเท่านั้น ดังนั้นเราจะจัดเลย์เอาท์ยังไงก็ช่าง ขอให้ภาพออกมาตรงตามต้องการก็เป็นพอ ผู้ใช้เค้าไม่รู้หรอกว่าเราจัดเลย์เอาท์อะไรแบบไหน"

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


       ดังนั้นเจ้าของบล็อกจึงนิยมใช้วิธีแบบนี้แทน


        ให้ Relative Layout เป็น Root ViewGroup แล้วใช้ ImageView ขยายเต็มหน้าจอแล้วกำหนดภาพพื้นหลังบนนี้แทน ส่วน View ทั้งหลายแหล่ก็กำหนดบน Any Layout อีกที โดยที่ Any Layout จะเป็น GroupView ตัวไหนๆก็ได้

        ทั้งนี้ก็เพราะว่า ImageView มีข้อดีตรงที่มี Attribute ที่เรียกว่า Scale Type อยู่ ที่มีข้อดีคือสามารถกำหนดเป็น Center Crop เพื่อให้ภาพขยายเต็มจอโดยที่อัตราส่วนภาพไม่เพี้ยน และส่วนที่เกินก็จะถูก Crop ทิ้งออกไป


        ดังนั้นเจ้าของบล็อกจึงใช้ข้อดีของ Image View นี่แหละมาทำเนียนเป็นภาพพื้นหลัง

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/sample" />


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true"
            android:layout_margin="20dp"
            android:text="@string/hello_world"
            android:textColor="#FFFFFF"
            android:textSize="30sp" />

    </RelativeLayout>
</RelativeLayout>



        เท่านี้ก็ได้ภาพพื้นหลังที่รองรับกับหน้าจอทุกขนาดแล้ว และจัดหน้าจอแอพตามปกติได้เลย



        ที่เหลือก็แค่ดูเรื่องความละเอียดของภาพที่ใช้ ซึ่งเจ้าของบล็อกไม่แนะนำให้ใช้ภาพใหญ่ๆเกิน 2048x2048 px เพราะเป็นขนาดสูงสุดของภาพที่ระบบแอนดรอยด์กำหนดไว้

        และถ้าเป็นไปได้ก็ควรทำภาพเป็นของขนาดคือหน้าจอความละเอียดสูง และความละเอียดต่ำ ไม่จำเป็นจำเป็นต้องทำทุกความละเอียดหน้าจอ เพราะจะทำให้ตัวแอพฯบวมใหญ่เกินจำเป็น