การออกแบบที่ปรับเปลี่ยนตามอุปกรณ์/ปรับเปลี่ยนได้พร้อมมุมมอง

ลองใช้วิธีเขียน
Jetpack Compose เป็นชุดเครื่องมือ UI ที่แนะนําสําหรับ Android ดูวิธีทำงานกับเลย์เอาต์ที่ปรับเปลี่ยนตามพื้นที่โฆษณาในเครื่องมือเขียน

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

การออกแบบที่ปรับเปลี่ยนตามอุปกรณ์

ขั้นตอนแรกในการรองรับรูปแบบของอุปกรณ์ที่หลากหลายคือการสร้างเลย์เอาต์ที่ปรับเปลี่ยนตามพื้นที่ในการแสดงผลที่มีให้สำหรับแอป

ConstraintLayout

วิธีที่ดีที่สุดในการสร้างเลย์เอาต์ที่ตอบสนองตามอุปกรณ์คือการใช้ ConstraintLayout เป็นเลย์เอาต์พื้นฐานสำหรับ UI ConstraintLayout ช่วยให้คุณระบุตำแหน่งและขนาดของมุมมองแต่ละรายการตามความสัมพันธ์เชิงพื้นที่กับมุมมองอื่นๆ ในเลย์เอาต์ จากนั้นมุมมองทั้งหมดจะย้ายและปรับขนาดพร้อมกันได้เมื่อพื้นที่แสดงผลเปลี่ยนแปลง

วิธีที่ง่ายที่สุดในการสร้างเลย์เอาต์ด้วย ConstraintLayout คือการใช้เครื่องมือแก้ไขเลย์เอาต์ใน Android Studio เครื่องมือแก้ไขเลย์เอาต์ช่วยให้คุณลากมุมมองใหม่ไปยังเลย์เอาต์ ใช้ข้อจำกัดที่เกี่ยวข้องกับมุมมองหลักและมุมมองพี่น้อง รวมถึงตั้งค่าพร็อพเพอร์ตี้ของมุมมองได้โดยไม่ต้องแก้ไข XML ด้วยตนเอง

รูปที่ 3 เครื่องมือสร้างเลย์เอาต์ใน Android Studio ที่แสดง ConstraintLayout

ดูข้อมูลเพิ่มเติมได้ที่สร้าง UI ที่ปรับเปลี่ยนตามอุปกรณ์ด้วย ConstraintLayout

ความกว้างและความสูงที่ปรับเปลี่ยนตามอุปกรณ์

หากต้องการให้เลย์เอาต์ปรับเปลี่ยนตามขนาดการแสดงผลต่างๆ ให้ใช้ wrap_content, match_parent หรือ 0dp (match constraint) สำหรับความกว้างและความสูงของคอมโพเนนต์มุมมองแทนค่าที่กำหนดไว้ล่วงหน้า ดังนี้

  • wrap_content: มุมมองจะตั้งค่าขนาดให้พอดีกับเนื้อหาที่มี
  • match_parent: มุมมองจะขยายมากที่สุดภายในมุมมองหลัก
  • 0dp (match constraint): ใน ConstraintLayout คล้ายกับ match_parent มุมมองจะใช้พื้นที่ว่างทั้งหมดภายในข้อจำกัดของมุมมอง

เช่น

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/lorem_ipsum" />

รูปที่ 4 แสดงวิธีที่ความกว้างและความสูงของ TextView ปรับตามความกว้างของจอแสดงผลที่เปลี่ยนแปลงตามการวางแนวของอุปกรณ์

รูปที่ 4 TextView ที่ปรับเปลี่ยนตามพื้นที่โฆษณา

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

หากใช้ LinearLayout คุณยังขยายมุมมองย่อยตามน้ำหนักเลย์เอาต์ได้ด้วยเพื่อให้มุมมองเต็มพื้นที่ว่างตามสัดส่วน อย่างไรก็ตาม การใช้น้ำหนักใน LinearLayout ที่ฝังอยู่จะทำให้ระบบต้องเรียกใช้เลย์เอาต์หลายครั้งเพื่อกำหนดขนาดสำหรับแต่ละมุมมอง ซึ่งจะทำให้ประสิทธิภาพของ UI ช้าลง

ConstraintLayout สร้างเลย์เอาต์ได้เกือบทั้งหมดด้วย LinearLayoutโดยไม่ส่งผลกระทบต่อประสิทธิภาพ ดังนั้นให้แปลง LinearLayout ที่ฝังอยู่เป็น ConstraintLayout จากนั้นคุณสามารถกําหนดเลย์เอาต์ที่มีน้ำหนักด้วยเชนข้อจํากัด

การออกแบบที่ปรับเปลี่ยนได้

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

SlidingPaneLayout สำหรับ UI รายละเอียดรายการ

โดยปกติแล้ว UI รายการแบบละเอียดจะให้ประสบการณ์การใช้งานที่แตกต่างกันในหน้าจอขนาดต่างๆ ในหน้าจอขนาดใหญ่ แผงรายการและแผงรายละเอียดมักจะอยู่เคียงข้างกัน เมื่อเลือกรายการในรายการ ข้อมูลรายการจะแสดงในแผงรายละเอียดโดยไม่มีการเปลี่ยนแปลง UI โดยแผงทั้ง 2 แผงจะยังคงอยู่เคียงข้างกัน อย่างไรก็ตาม ในหน้าจอขนาดเล็ก แผง 2 แผงจะแสดงแยกกัน โดยแต่ละแผงจะกินพื้นที่ทั้งหน้าจอ เมื่อเลือกรายการในแผงรายการแล้ว แผงรายละเอียด (ซึ่งมีข้อมูลของรายการที่เลือก) จะแทนที่แผงรายการ การนําทางกลับจะแทนที่แผงรายละเอียดด้วยรายการ

SlidingPaneLayout จัดการตรรกะในการระบุว่าประสบการณ์ของผู้ใช้แบบใดเหมาะสําหรับขนาดกรอบปัจจุบัน

<?xml version="1.0" encoding="utf-8"?>
<androidx.slidingpanelayout.widget.SlidingPaneLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="280dp"
        android:layout_height="match_parent"
        android:layout_gravity="start" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        app:defaultNavHost="true"
        app:navGraph="@navigation/item_navigation" />

</androidx.slidingpanelayout.widget.SlidingPaneLayout>

แอตทริบิวต์ layout_width และ layout_weight ของมุมมอง 2 รายการที่อยู่ใน SlidingPaneLayout จะกำหนดลักษณะการทํางานของ SlidingPaneLayout ในตัวอย่างนี้ หากหน้าต่างมีขนาดใหญ่พอ (กว้างอย่างน้อย 580dp) เพื่อแสดงทั้ง 2 มุมมอง แผงจะแสดงคู่กัน แต่หากความกว้างของหน้าต่างน้อยกว่า 580dp แผงจะเลื่อนทับกันเพื่อใช้พื้นที่ทั้งหน้าต่างแอป

หากความกว้างของหน้าต่างมากกว่าความกว้างขั้นต่ำทั้งหมดที่ระบุ (580dp) ระบบจะใช้ค่า layout_weight เพื่อปรับขนาดของ 2 แผงตามสัดส่วน ในตัวอย่างนี้ แผงรายการจะกว้าง 280dp เสมอเนื่องจากไม่มีน้ำหนัก อย่างไรก็ตาม แผงรายละเอียดจะเติมเต็มพื้นที่แนวนอนที่เกิน 580dp เสมอเนื่องจากการตั้งค่า layout_weight ของมุมมอง

ทรัพยากรเลย์เอาต์สำรอง

หากต้องการปรับการออกแบบ UI ให้เหมาะกับขนาดการแสดงผลที่หลากหลาย ให้ใช้เลย์เอาต์อื่นที่ระบุโดยตัวระบุทรัพยากร

รูปที่ 5 แอปเดียวกันที่ใช้เลย์เอาต์ที่แตกต่างกันสำหรับขนาดการแสดงผลที่แตกต่างกัน

คุณสามารถระบุเลย์เอาต์ที่ปรับเปลี่ยนตามหน้าจอได้โดยสร้างไดเรกทอรี res/layout/ เพิ่มเติมในซอร์สโค้ดของแอป สร้างไดเรกทอรีสําหรับการกําหนดค่าหน้าจอแต่ละรายการที่ต้องใช้เลย์เอาต์ที่แตกต่างกัน จากนั้นเพิ่มตัวระบุการกําหนดค่าหน้าจอต่อท้ายชื่อไดเรกทอรี layout (เช่น layout-w600dp สําหรับหน้าจอที่มีความกว้าง 600 dp)

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

หากต้องการสร้างเลย์เอาต์อื่นใน Android Studio โปรดดูใช้ตัวแปรเลย์เอาต์เพื่อเพิ่มประสิทธิภาพสำหรับหน้าจอต่างๆ ในหัวข้อพัฒนา UI ด้วยมุมมอง

ตัวระบุความกว้างที่เล็กที่สุด

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

การอธิบายขนาดหน้าจอเป็นหน่วยวัด dp จะช่วยให้ Android ช่วยคุณสร้างเลย์เอาต์ที่ออกแบบมาสำหรับมิติข้อมูลการแสดงผลที่เฉพาะเจาะจงได้โดยไม่ต้องกังวลเกี่ยวกับความหนาแน่นของพิกเซลที่แตกต่างกัน

เช่น คุณสามารถสร้างเลย์เอาต์ชื่อ main_activity ที่ปรับให้เหมาะกับโทรศัพท์และแท็บเล็ตโดยการสร้างไฟล์เวอร์ชันต่างๆ ในไดเรกทอรีต่างๆ ดังนี้

res/layout/main_activity.xml           # For phones (smaller than 600dp smallest width)
res/layout-sw600dp/main_activity.xml   # For 7" tablets (600dp wide or wider)

ตัวระบุความกว้างที่เล็กที่สุดจะระบุขนาดที่เล็กที่สุดของจอแสดงผล 2 ด้าน โดยไม่คำนึงถึงการวางแนวปัจจุบันของอุปกรณ์ ดังนั้นจึงเป็นวิธีระบุขนาดจอแสดงผลโดยรวมที่ใช้ได้กับเลย์เอาต์

ค่าความกว้างที่เล็กที่สุดอื่นๆ สอดคล้องกับขนาดหน้าจอทั่วไปดังนี้

  • 320dp: หน้าจอโทรศัพท์ขนาดเล็ก (240x320 ldpi, 320x480 mdpi, 480x800 hdpi ฯลฯ)
  • 480dp: หน้าจอโทรศัพท์ขนาดใหญ่ ~5" (480x800 mdpi)
  • 600dp: แท็บเล็ตขนาด 7 นิ้ว (600x1024 mdpi)
  • 720dp: แท็บเล็ตขนาด 10 นิ้ว (720x1280 mdpi, 800x1280 mdpi ฯลฯ)

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

รูปที่ 6 จุดพักความกว้างที่แนะนําเพื่อรองรับหน้าจอขนาดต่างๆ

ค่าสำหรับตัวระบุความกว้างน้อยที่สุดคือ dp เนื่องจากสิ่งสำคัญคือปริมาณพื้นที่ในการแสดงผลที่มีให้หลังจากระบบพิจารณาความหนาแน่นของพิกเซลแล้ว (ไม่ใช่ความละเอียดพิกเซลดิบ)

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

ตัวคําจํากัดความกว้างที่ใช้ได้

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

res/layout/main_activity.xml         # For phones (smaller than 600dp available width)
res/layout-w600dp/main_activity.xml  # For 7" tablets or any screen with 600dp available width
                                     # (possibly landscape phones)

หากความสูงที่ใช้ได้เป็นสิ่งที่น่ากังวลสำหรับแอป คุณสามารถใช้ตัวระบุความสูงที่ใช้ได้ เช่น layout-h600dp สำหรับหน้าจอที่มีความสูงของหน้าจออย่างน้อย 600 DP

ตัวระบุการวางแนว

แม้ว่าคุณอาจรองรับรูปแบบขนาดทั้งหมดได้โดยใช้เฉพาะการรวมตัวระบุความกว้างน้อยที่สุดและความกว้างที่ใช้ได้ แต่คุณอาจต้องเปลี่ยนประสบการณ์ของผู้ใช้ด้วยเมื่อผู้ใช้สลับระหว่างการวางแนวตั้งและแนวนอน

โดยคุณสามารถเพิ่มตัวระบุ port หรือ land ลงในชื่อไดเรกทอรีเลย์เอาต์ได้ เพียงตรวจสอบว่าตัวระบุการวางแนวอยู่หลังตัวระบุขนาด เช่น

res/layout/main_activity.xml                # For phones
res/layout-land/main_activity.xml           # For phones in landscape
res/layout-sw600dp/main_activity.xml        # For 7" tablets
res/layout-sw600dp-land/main_activity.xml   # For 7" tablets in landscape

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

คลาสขนาดหน้าต่าง

Window Size Class คือจุดพักของวิวพอร์ตที่ช่วยให้คุณสร้างเลย์เอาต์ที่ปรับเปลี่ยนได้ เบรกพอยท์จะระบุพื้นที่แสดงผลที่พร้อมใช้งานสำหรับแอปของคุณเป็นกะทัดรัด กลาง หรือขยาย ความกว้างและความสูงจะระบุแยกกันเพื่อให้แอปมี Window Size Class สำหรับความกว้างและ Window Size Class สำหรับความสูงเสมอ

หากต้องการใช้เลย์เอาต์แบบปรับเปลี่ยนได้แบบเป็นโปรแกรม ให้ทําดังนี้

  • สร้างทรัพยากรเลย์เอาต์ตามจุดหยุดพักของคลาสขนาดหน้าต่าง
  • คํานวณคลาสขนาดหน้าต่างของแอปในด้านความกว้างและความสูงโดยใช้ฟังก์ชัน WindowSizeClass#compute() จากไลบรารี Jetpack WindowManager
  • ขยายทรัพยากรเลย์เอาต์สำหรับคลาสขนาดหน้าต่างปัจจุบัน

ดูข้อมูลเพิ่มเติมได้ที่ชั้นเรียนขนาดกรอบเวลา

คอมโพเนนต์ UI แบบโมดูลโดยใช้ส่วนย่อย

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

เช่น รูปแบบรายการแบบมีรายละเอียด (ดูSlidingPaneLayout ด้านบน) อาจใช้กับข้อมูลโค้ดที่หนึ่งซึ่งมีรายการ และข้อมูลโค้ดอีกรายการซึ่งมีรายละเอียดรายการ บนหน้าจอขนาดใหญ่ ข้อมูลโค้ดจะแสดงคู่กัน ส่วนบนหน้าจอขนาดเล็ก ข้อมูลโค้ดจะแสดงทีละรายการจนเต็มหน้าจอ

ดูข้อมูลเพิ่มเติมได้ที่ภาพรวมข้อมูลโค้ด

การฝังกิจกรรม

หากแอปประกอบด้วยกิจกรรมหลายรายการ การฝังกิจกรรมจะช่วยให้คุณสร้าง UI แบบปรับเปลี่ยนได้ง่ายๆ

การฝังกิจกรรมจะแสดงกิจกรรมหลายรายการหรือหลายอินสแตนซ์ของกิจกรรมเดียวกันพร้อมกันในหน้าต่างงานของแอปพลิเคชัน บนหน้าจอขนาดใหญ่ กิจกรรมจะแสดงคู่กัน ส่วนบนหน้าจอขนาดเล็ก กิจกรรมจะซ้อนกัน

คุณกำหนดวิธีแสดงกิจกรรมของแอปได้โดยการสร้างไฟล์การกำหนดค่า XML ซึ่งระบบจะใช้เพื่อกำหนดการแสดงผลที่เหมาะสมตามขนาดหน้าจอ หรือจะเรียกใช้ Jetpack WindowManager APIก็ได้

การฝังกิจกรรมรองรับการเปลี่ยนแปลงการวางแนวของอุปกรณ์และอุปกรณ์แบบพับได้ รวมถึงการซ้อนและเลิกซ้อนกิจกรรมเมื่ออุปกรณ์หมุนหรือพับออกและกางออก

ดูข้อมูลเพิ่มเติมได้ที่การฝังกิจกรรม

ขนาดหน้าจอและสัดส่วนภาพ

ทดสอบแอปในหน้าจอขนาดต่างๆ และอัตราส่วนภาพเพื่อให้แน่ใจว่า UI ปรับขนาดได้อย่างถูกต้อง

Android 10 (API ระดับ 29) ขึ้นไปรองรับสัดส่วนภาพได้หลากหลาย รูปแบบของอุปกรณ์แบบพับได้อาจแตกต่างกันไปตั้งแต่หน้าจอสูงและแคบ เช่น 21:9 เมื่อพับไปจนถึงสัดส่วนภาพสี่เหลี่ยมจัตุรัส 1:1 เมื่อกางออก

โปรดทดสอบแอปสำหรับสัดส่วนภาพหน้าจอต่อไปนี้ให้ได้มากที่สุดเพื่อให้เข้ากันได้กับอุปกรณ์จำนวนมากที่สุด

รูปที่ 7 สัดส่วนภาพหน้าจอต่างๆ

หากไม่มีสิทธิ์เข้าถึงอุปกรณ์ที่มีหน้าจอทุกขนาดที่ต้องการทดสอบ คุณสามารถใช้โปรแกรมจำลอง Android เพื่อจำลองหน้าจอเกือบทุกขนาด

หากต้องการทดสอบบนอุปกรณ์จริงแต่ไม่มีอุปกรณ์ คุณสามารถใช้ Firebase Test Lab เพื่อเข้าถึงอุปกรณ์ในศูนย์ข้อมูลของ Google

แหล่งข้อมูลเพิ่มเติม