แอป Android ต้องรองรับระบบนิเวศของรูปแบบอุปกรณ์ที่ขยายตัวอย่างต่อเนื่อง UI ของแอปควรปรับเปลี่ยนให้เหมาะกับหน้าจอขนาดต่างๆ รวมถึงการวางแนวและสถานะอุปกรณ์ที่แตกต่างกัน
UI แบบปรับเปลี่ยนตามอุปกรณ์มุ่งเน้นที่หลักการของความยืดหยุ่นและความต่อเนื่อง
ความยืดหยุ่นหมายถึงเลย์เอาต์ที่ใช้ประโยชน์จากพื้นที่ที่มีอยู่อย่างคุ้มค่าที่สุดและปรับเมื่อพื้นที่ที่มีอยู่เปลี่ยนแปลง การปรับอาจทำได้หลายวิธี เช่น เพียงขยายขนาดของมุมมองเดียว เปลี่ยนตำแหน่งมุมมองเพื่อให้เข้าถึงได้ง่ายขึ้น แสดงหรือซ่อนมุมมองเพิ่มเติม หรือใช้วิธีเหล่านี้ร่วมกัน
ความต่อเนื่องหมายถึงประสบการณ์การใช้งานที่ราบรื่นของผู้ใช้ขณะเปลี่ยนจากหน้าต่างขนาดหนึ่งไปยังอีกขนาดหนึ่ง ประสบการณ์การใช้งานใดก็ตามที่ผู้ใช้มีส่วนร่วมอยู่ควรดำเนินต่อไปโดยไม่หยุดชะงัก เนื่องจากการเปลี่ยนแปลงขนาดอาจมาพร้อมกับการทำลายและการสร้างลําดับชั้นมุมมองทั้งหมดขึ้นใหม่ จึงเป็นเรื่องสําคัญที่ผู้ใช้จะไม่สูญเสียตําแหน่งหรือข้อมูล
สิ่งที่ควรหลีกเลี่ยง
หลีกเลี่ยงการใช้ค่าฮาร์ดแวร์จริงในการตัดสินใจเกี่ยวกับเลย์เอาต์ คุณอาจอยากตัดสินใจตามค่าคงที่ แต่ในกรณีหลายกรณี ค่าเหล่านี้ไม่มีประโยชน์ในการกำหนดพื้นที่ที่ UI ของคุณใช้งานได้
แอปอาจมีการปรับเปลี่ยนขนาดหน้าต่างเมื่อทำงานในโหมดหลายหน้าต่าง ภาพซ้อนภาพ หรือหน้าต่างรูปแบบอิสระ เช่น ChromeOS อุปกรณ์อาจมีหน้าจอจริงมากกว่า 1 หน้าจอ เช่น อุปกรณ์แบบพับได้หรืออุปกรณ์ที่มีจอแสดงผลหลายจอ ในทุกกรณีเหล่านี้ ขนาดหน้าจอจริงไม่เกี่ยวข้องกับการตัดสินใจเลือกวิธีแสดงเนื้อหา
ด้วยเหตุผลเดียวกันนี้ โปรดหลีกเลี่ยงการล็อกแอปให้อยู่ในการวางแนวหรือสัดส่วนภาพที่เจาะจง แม้ว่าอุปกรณ์เองอาจอยู่ในการวางแนวหนึ่งๆ แต่แอปของคุณอาจอยู่ในการวางแนวอื่นโดยอิงตามขนาดของหน้าต่างเท่านั้น ตัวอย่างเช่น บนแท็บเล็ตในแนวนอนขณะใช้โหมดหลายหน้าต่าง แอปอาจอยู่ในแนวตั้งได้เนื่องจากมีความสูงมากกว่าความกว้าง
นอกจากนี้ อย่าพยายามระบุว่าอุปกรณ์เป็นโทรศัพท์หรือแท็บเล็ต อุปกรณ์ที่ถือเป็นแท็บเล็ตนั้นค่อนข้างเป็นแนวคิดที่ขึ้นอยู่กับความคิดเห็นของแต่ละบุคคล เช่น อุปกรณ์ดังกล่าวต้องมีขนาดหรือสัดส่วนภาพใดๆ เป็นพิเศษ หรือต้องมีขนาดและสัดส่วนภาพรวมกัน เมื่อรูปแบบของอุปกรณ์ใหม่เกิดขึ้น สมมติฐานเหล่านี้ก็อาจเปลี่ยนแปลงไป และความแตกต่างก็ไม่มีความหมาย
ใช้เบรกพอยต์และคลาสขนาดหน้าต่างแทนที่จะลองใช้กลยุทธ์ข้างต้น
จุดหยุดพักและคลาสขนาดหน้าต่าง
ส่วนจริงของหน้าจอที่จัดสรรให้กับแอปคือหน้าต่างของแอป หน้าต่างอาจกินพื้นที่ทั้งหน้าจอหรือบางส่วนของหน้าจอ ดังนั้นให้ใช้ขนาดหน้าต่างเมื่อตัดสินใจในระดับสูงเกี่ยวกับเลย์เอาต์ของแอป
เมื่อออกแบบสำหรับรูปแบบอุปกรณ์หลายรูปแบบ ให้หาค่าเกณฑ์ที่การตัดสินใจระดับสูงเหล่านี้แยกออกเป็นหลายทิศทาง ด้วยเหตุนี้ ตารางกริดเลย์เอาต์ที่ปรับเปลี่ยนตามพื้นที่โฆษณาของ Material Design จึงระบุเบรกพอยต์สำหรับความกว้างและความสูง ซึ่งช่วยให้คุณจับคู่ขนาดดิบเป็นกลุ่มๆ ที่แยกกันตามมาตรฐานและเรียกว่า Window Size Classes เนื่องจากการเลื่อนแนวตั้งมีการใช้งานอย่างแพร่หลาย แอปส่วนใหญ่จึงให้ความสำคัญกับคลาสขนาดความกว้างเป็นหลัก แอปส่วนใหญ่จึงได้รับการเพิ่มประสิทธิภาพสำหรับหน้าจอทุกขนาดได้โดยจัดการจุดหยุดพักเพียงไม่กี่จุด (ดูข้อมูลเพิ่มเติมเกี่ยวกับคลาสขนาดหน้าต่างได้ที่ใช้คลาสขนาดหน้าต่าง)
องค์ประกอบ UI ถาวร
หลักเกณฑ์เลย์เอาต์ของ Material Design จะกำหนดพื้นที่สำหรับแถบแอป การไปยังส่วนต่างๆ และเนื้อหา โดยทั่วไปแล้ว 2 รายการแรกจะเป็นองค์ประกอบ UI ถาวรที่ (หรือใกล้กับ) รูทของลําดับชั้นมุมมอง โปรดทราบว่า "คงที่" ไม่ได้หมายความว่ามุมมองจะปรากฏอยู่เสมอ แต่หมายความว่ามุมมองจะยังคงอยู่ในตำแหน่งเดิมขณะที่มุมมองเนื้อหาอื่นๆ อาจย้ายหรือเปลี่ยนแปลง เช่น องค์ประกอบการนําทางอาจอยู่ในลิ้นชักแบบเลื่อนที่อยู่นอกหน้าจอ แต่ลิ้นชักจะปรากฏอยู่เสมอ
องค์ประกอบถาวรอาจปรับเปลี่ยนตามอุปกรณ์ได้ และมักจะกินพื้นที่ทั้งความกว้างหรือความสูงของหน้าต่าง ดังนั้นจึงควรใช้คลาสขนาดเพื่อกำหนดตำแหน่งที่จะวางองค์ประกอบ ซึ่งจะกำหนดพื้นที่ที่เหลือสำหรับเนื้อหา ในสนิปเพลตต่อไปนี้ กิจกรรมใช้แถบด้านล่างสำหรับหน้าจอขนาดเล็กและแถบแอปด้านบนสำหรับหน้าจอขนาดใหญ่ เลย์เอาต์ที่เข้าเกณฑ์จะใช้จุดหยุดความกว้างตามที่อธิบายไว้ก่อนหน้านี้
<!-- res/layout/main_activity.xml -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- content view(s) -->
<com.google.android.material.bottomappbar.BottomAppBar
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
... />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- res/layout-w600dp/main_activity.xml -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
... />
<!-- content view(s) -->
</androidx.constraintlayout.widget.ConstraintLayout>
เนื้อหา
เมื่อวางองค์ประกอบ UI ถาวรแล้ว ให้ใช้พื้นที่ที่เหลือสำหรับเนื้อหา เช่น การใช้ NavHostFragment
กับกราฟการนําทางของแอป ดูข้อควรพิจารณาเพิ่มเติมได้จากการนําทางสําหรับ UI แบบตอบสนอง
ตรวจสอบว่าข้อมูลทั้งหมดพร้อมใช้งานสำหรับขนาดต่างๆ
ปัจจุบันเฟรมเวิร์กแอปส่วนใหญ่ใช้โมเดลข้อมูลที่แยกจากคอมโพเนนต์ Android ที่ส่งผลต่อ UI (กิจกรรม ฟragment และมุมมอง) เมื่อใช้ Jetpack บทบาทนี้มักจะเป็นหน้าที่ของ ViewModel ซึ่งมีข้อดีเพิ่มเติมคือสามารถอยู่รอดได้แม้จะมีการเปลี่ยนแปลงการกําหนดค่า (ดูข้อมูลเพิ่มเติมในภาพรวม ViewModel)
เมื่อใช้เลย์เอาต์ที่ปรับขนาดได้ คุณอาจต้องการใช้โมเดลข้อมูลอื่นตามขนาดปัจจุบัน อย่างไรก็ตาม วิธีนี้ขัดต่อหลักการของการรับส่งข้อมูลแบบทิศทางเดียว ข้อมูลควรไหลลงไปยังมุมมอง และเหตุการณ์ต่างๆ เช่น การโต้ตอบของผู้ใช้ควรไหลขึ้น การสร้างการพึ่งพาในอีกทิศทางหนึ่ง ซึ่งโมเดลข้อมูลขึ้นอยู่กับการกำหนดค่าของเลเยอร์ UI จะทําให้กระบวนการนี้ซับซ้อนขึ้นอย่างมาก เมื่อแอปเปลี่ยนขนาด คุณต้องพิจารณาการแปลงจากรูปแบบข้อมูลหนึ่งเป็นรูปแบบอื่น
แต่ให้โมเดลข้อมูลรองรับคลาสขนาดที่ใหญ่ที่สุด แล้วคุณก็เลือกแสดง ซ่อน หรือจัดตำแหน่งเนื้อหาใน UI เพื่อปรับให้เข้ากับคลาสขนาดปัจจุบันได้ ด้านล่างนี้คือกลยุทธ์บางส่วนที่คุณใช้ได้เมื่อตัดสินใจว่าเลย์เอาต์ควรทำงานอย่างไรเมื่อเปลี่ยนระหว่างคลาสขนาด
ขยายเนื้อหา
เลย์เอาต์ตามรูปแบบบัญญัติ: ฟีด
พื้นที่ที่เพิ่มขึ้นอาจเป็นโอกาสในการขยายขนาดและจัดรูปแบบเนื้อหาใหม่เพื่อให้เข้าถึงได้ง่ายขึ้น
ทำให้คอลเล็กชันมีขนาดใหญ่ขึ้น แอปจำนวนมากแสดงคอลเล็กชันรายการต่างๆ ในคอนเทนเนอร์แบบเลื่อน เช่น RecyclerView
หรือ ScrollView
การเปิดใช้คอนเทนเนอร์ให้มีขนาดโตขึ้นโดยอัตโนมัติจะทำให้แสดงเนื้อหาได้มากขึ้น
อย่างไรก็ตาม โปรดระวังอย่าให้เนื้อหาภายในคอนเทนเนอร์ยืดหรือบิดเบี้ยวมากเกินไป เช่น หากใช้ RecyclerView
ให้พิจารณาใช้เครื่องมือจัดการเลย์เอาต์อื่น เช่น GridLayoutManager
, StaggeredGridLayoutManager
หรือ FlexboxLayout
เมื่อความกว้างไม่กะทัดรัด
รายการแต่ละรายการยังใช้ขนาดหรือรูปร่างที่แตกต่างกันเพื่อแสดงเนื้อหาได้มากขึ้นและแยกขอบเขตของรายการได้ง่ายขึ้น
เน้นองค์ประกอบหลัก หากเลย์เอาต์มีจุดโฟกัสที่เฉพาะเจาะจง เช่น รูปภาพหรือวิดีโอ ให้ขยายเลย์เอาต์เมื่อหน้าต่างแอปขยายขึ้นเพื่อรักษาความสนใจของผู้ใช้ องค์ประกอบสนับสนุนอื่นๆ สามารถจัดเรียงใหม่รอบๆ หรือใต้มุมมองฮีโร่ได้
การสร้างเลย์เอาต์ดังกล่าวมีหลายวิธี แต่ ConstraintLayout
เหมาะอย่างยิ่งสําหรับวัตถุประสงค์นี้เนื่องจากมีวิธีจํานวนมากในการจํากัดขนาดของมุมมองย่อย ซึ่งรวมถึงการจำกัดด้วยเปอร์เซ็นต์หรือการบังคับใช้สัดส่วนการแสดงผล และเพื่อจัดตําแหน่งมุมมองย่อยตามความสัมพันธ์กับมุมมองย่อยอื่นๆ หรือกับตัวมุมมองย่อยเอง ดูข้อมูลเพิ่มเติมเกี่ยวกับความสามารถทั้งหมดเหล่านี้ได้ในหัวข้อสร้าง UI ที่ปรับเปลี่ยนตามอุปกรณ์ด้วย ConstraintLayout
แสดงเนื้อหาแบบยุบได้โดยค่าเริ่มต้น เมื่อมีพื้นที่ว่าง ให้แสดงเนื้อหาที่ผู้ใช้เข้าถึงได้ผ่านการทำงานเพิ่มเติม เช่น การแตะ การเลื่อน หรือท่าทางสัมผัส ตัวอย่างเช่น เนื้อหาที่ปรากฏในอินเทอร์เฟซแบบแท็บเมื่อเป็นแบบกะทัดรัดอาจจัดเรียงใหม่เป็นคอลัมน์หรือรายการได้เมื่อมีพื้นที่มากขึ้น
ขยายระยะขอบ หากพื้นที่มีขนาดใหญ่มากจนคุณหาขนาดที่พอดีและน่าสนใจไม่ได้ แม้ว่าจะใช้เนื้อหาทั้งหมดแล้ว ให้ขยายระยะขอบของเลย์เอาต์เพื่อให้เนื้อหาอยู่ตรงกลางและแต่ละมุมมองมีขนาดและระยะห่างที่เหมาะสม
หรือคอมโพเนนต์แบบเต็มหน้าจออาจเปลี่ยนรูปแบบเป็นกล่องโต้ตอบแบบลอยอยู่ก็ได้ ซึ่งเหมาะอย่างยิ่งเมื่อคอมโพเนนต์นั้นต้องใช้โฟกัสเฉพาะเพื่อทำงานของผู้ใช้ในทันที เช่น การเขียนอีเมลหรือการสร้างกิจกรรมในปฏิทิน
เพิ่มเนื้อหา
เลย์เอาต์ตามรูปแบบบัญญัติ: แผงสนับสนุน มุมมองรายการแบบละเอียด
ใช้แผงสนับสนุน แผงสนับสนุนจะแสดงเนื้อหาเพิ่มเติมหรือการดำเนินการตามบริบทที่เกี่ยวข้องกับเนื้อหาหลัก เช่น ความคิดเห็นในเอกสารหรือรายการในเพลย์ลิสต์ โดยปกติแล้ว โฆษณาเหล่านี้จะใช้ส่วนล่าง 1 ใน 3 ของหน้าจอสำหรับความสูงที่ขยายหรือส่วนท้าย 1 ใน 3 สำหรับความกว้างที่ขยาย
สิ่งที่ควรพิจารณาที่สำคัญคือตําแหน่งที่จะวางเนื้อหานี้เมื่อมีพื้นที่ไม่เพียงพอที่จะแสดงแผง ตัวอย่างทางเลือกอื่นๆ มีดังนี้
- ลิ้นชักด้านข้างที่ขอบท้ายโดยใช้
DrawerLayout
- ลิ้นชักด้านล่างที่ใช้
BottomSheetBehavior
- เมนูหรือหน้าต่างป๊อปอัปที่เข้าถึงได้ด้วยการแตะไอคอนเมนู
สร้างเลย์เอาต์แบบ 2 แผง หน้าจอขนาดใหญ่อาจแสดงการผสมผสานฟีเจอร์ต่างๆ ที่ปกติจะปรากฏแยกกันในหน้าจอขนาดเล็ก รูปแบบการโต้ตอบที่พบบ่อยในแอปหลายแอปคือการแสดงรายการรายการต่างๆ เช่น รายชื่อติดต่อหรือผลการค้นหา และเปลี่ยนไปดูรายละเอียดของรายการเมื่อเลือกรายการนั้น ใช้มุมมองรายละเอียดรายการเพื่อแสดงฟีเจอร์ทั้ง 2 รายการควบคู่กันในเลย์เอาต์แบบ 2 หน้าจอแทนการขยายรายการสำหรับหน้าจอขนาดใหญ่ แผงรายละเอียดของมุมมองรายละเอียดรายการเป็นองค์ประกอบแบบสแตนด์อโลนที่แสดงในหน้าจอขนาดเล็กได้โดยไม่ขึ้นอยู่กับแผงสนับสนุน
ใช้วิดเจ็ตที่เฉพาะเจาะจงสำหรับการใช้มุมมองรายละเอียดรายการ
SlidingPaneLayout
วิดเจ็ตนี้จะคำนวณโดยอัตโนมัติว่ามีพื้นที่เพียงพอที่จะแสดงทั้ง 2 แผงร่วมกันหรือไม่ โดยอิงตามค่า layout_width
ที่ระบุสำหรับทั้ง 2 แผง และสามารถกระจายพื้นที่ที่เหลือโดยใช้ layout_weight
เมื่อมีพื้นที่ไม่เพียงพอ แต่ละแผงจะใช้ความกว้างเต็มรูปแบบของเลย์เอาต์ และแผงรายละเอียดจะเลื่อนออกไปนอกหน้าจอหรืออยู่ด้านบนของแผงรายการ
สร้างเลย์เอาต์แบบ 2 แผงมีรายละเอียดเพิ่มเติมเกี่ยวกับการใช้ SlidingPaneLayout
นอกจากนี้ โปรดทราบว่ารูปแบบนี้อาจส่งผลต่อโครงสร้างกราฟการนําทาง (ดูการนําทางสําหรับ UI ที่ปรับเปลี่ยนตามอุปกรณ์)
แหล่งข้อมูลเพิ่มเติม
- Material Design — การใช้เลย์เอาต์
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- สร้างเลย์เอาต์แบบ 2 แผง
- การออกแบบที่ปรับเปลี่ยนตามอุปกรณ์/แบบปรับเปลี่ยนได้พร้อมมุมมอง
- เลย์เอาต์ตามรูปแบบบัญญัติ