Screen Continuity — กลไกของ Android ที่รับประกันการเปลี่ยนผ่านที่ราบรื่นของแอประหว่างสถานะพับและกางออกของอุปกรณ์พับได้ เมื่อกางออก หน้าจอจะเปลี่ยนขนาดทางกายภาพ และระบบจะรีสตาร์ท Activity ด้วยการกำหนดค่าใหม่ ตาม Google Developer, 2025 การจัดการความต่อเนื่องที่ถูกต้องช่วยปรับปรุงประสบการณ์ผู้ใช้ 40% และลดข้อร้องเรียนเกี่ยวกับการสูญเสียสถานะ API ScreenContinuity เป็นส่วนหนึ่งของ Jetpack WindowManager ตั้งแต่เวอร์ชัน 1.1 และช่วยให้นักพัฒนาจัดการวงจรชีวิตเมื่อท่าทางของอุปกรณ์เปลี่ยนไป
ประเด็นสำคัญ
Screen Continuity เป็นกลไกของ Android ที่รักษาสถานะ Activity เมื่อการกำหนดค่าทางกายภาพของหน้าจอเปลี่ยนไปบนอุปกรณ์พับได้ เมื่อผู้ใช้กางหรือพับโทรศัพท์ ระบบอาจรีสตาร์ท Activity ด้วยขนาดหน้าต่างใหม่ ความต่อเนื่องป้องกันการสูญเสียข้อมูลที่ป้อน ตำแหน่งการเลื่อน และหน้าจอปัจจุบัน
แตกต่างจากการหมุนหน้าจอทั่วไปที่ Android เพียงสร้าง Activity ใหม่ด้วยทิศทางใหม่ อุปกรณ์พับได้นำเสนอสถานการณ์ใหม่โดยพื้นฐาน ท่าทาง HALF_OPENED ช่วยให้แอปทำงานบนครึ่งหน้าจอ ในขณะที่ FLAT ทำงานในโหมดแท็บเล็ตที่กางออกเต็มที่ หากไม่มีการสนับสนุน Screen Continuity การเปลี่ยนท่าทางแต่ละครั้งจะรีเซ็ตอินเทอร์เฟซกลับไปยังสถานะเริ่มต้น
ตาม Google I/O 2024 ผู้ใช้อุปกรณ์พับได้มากกว่า 62% พบกับแอปที่จัดการการเปลี่ยนสถานะอย่างไม่ถูกต้อง Screen Continuity แก้ปัญหานี้ในระดับ API โดยมอบเครื่องมือพร้อมใช้แก่นักพัฒนาในการบันทึกและกู้คืนอินเทอร์เฟซผู้ใช้
Jetpack WindowManager กำหนดท่าทางพื้นฐานสามแบบสำหรับอุปกรณ์พับได้ผ่านคลาส FoldingFeature แต่ละท่าทางสอดคล้องกับตำแหน่งทางกายภาพเฉพาะของบานพับและต้องการการจัดการอินเทอร์เฟซพิเศษ
อุปกรณ์อยู่ในมุม 30 ถึง 160 องศา หน้าจอแบ่งออกเป็นสองพื้นที่เชิงตรรกะ แอปสามารถแสดงเนื้อหาที่ครึ่งบนและส่วนควบคุมที่ครึ่งล่าง โหมด tabletop สำหรับการสนทนาทางวิดีโอและเครื่องเล่นสื่อใช้ท่าทางนี้
อุปกรณ์เปิด 180 องศา เกิดเป็นหน้าจอขนาดใหญ่เดียว แอปสลับไปยัง โหมดแท็บเล็ต ที่มีพื้นที่ทำงานขยายใหญ่ขึ้น ในท่าทางนี้ แนะนำให้แสดงเลย์เอาต์หลายแผงพร้อมแผงนำทางและเนื้อหาโดยละเอียดเคียงข้างกัน
อุปกรณ์ตั้งบนพื้นผิวในมุมประมาณ 120 องศา ครึ่งล่างของหน้าจอทำหน้าที่เป็นแผงสัมผัสหรือแป้นพิมพ์ โหมด touchpad ในท่าทางนี้ช่วยให้จำลองแทร็กแพดบนส่วนล่างของหน้าจอได้
Android จัดการการเปลี่ยนแปลงการกำหนดค่าอุปกรณ์พับได้ผ่านกลไก configuration changes เมื่อผู้ใช้กางโทรศัพท์ ระบบตรวจจับการเปลี่ยนแปลงขนาดหน้าต่างและเริ่มวงจรการสร้าง Activity ใหม่มาตรฐาน Screen Continuity สกัดกั้นกระบวนการนี้และบันทึกข้อมูลสำคัญ
วิธีการหลักในการบันทึกสถานะคือ onRetainNonConfigurationInstance ซึ่งถูกเรียกก่อนที่ Activity จะถูกทำลาย นักพัฒนาบันทึกโมเดลข้อมูล ตำแหน่งรายการ และหน้าจอการนำทางปัจจุบันไว้ในนั้น หลังจากสร้างใหม่ Activity จะได้รับข้อมูลนี้ผ่าน getLastNonConfigurationInstance และกู้คืน UI ตรงตามที่อยู่ก่อนพับ
สำหรับ Fragments กลไกนี้ implement ผ่าน setRetainInstance(true) ซึ่งป้องกันไม่ให้ fragment ถูกทำลายเมื่อมีการเปลี่ยนแปลงการกำหนดค่า ใน Jetpack Compose จะใช้ rememberSaveable ซึ่งบันทึกสถานะโดยอัตโนมัติเมื่อ Window Metrics เปลี่ยนไป
class MainActivity : AppCompatActivity() {
private var currentScrollPosition: Int = 0
override fun onRetainNonConfigurationInstance(): Any {
return SavedState(scrollPosition = currentScrollPosition)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val saved = lastNonConfigurationInstance as? SavedState
saved?.let { currentScrollPosition = it.scrollPosition }
}
}
Jetpack WindowManager เวอร์ชัน 1.1+ มีคลาส ScreenContinuityController ซึ่งมีกลไกพร้อมใช้สำหรับจัดการความต่อเนื่องของหน้าจอ API จัดการการเปลี่ยนท่าทางโดยอัตโนมัติและแจ้งให้แอปทราบผ่านอินเทอร์เฟซ callback
คลาสกลางที่ลงทะเบียนตัวฟังการเปลี่ยนท่าทาง registerContinuityListener ยอมรับ callback ที่ถูกเรียกในทุกการเปลี่ยนระหว่างสถานะของอุปกรณ์พับได้ ตัวควบคุมยังให้ข้อมูลเกี่ยวกับท่าทางปัจจุบันผ่านเมธอด getCurrentFoldingFeature
คลาสอรรถประโยชน์สำหรับแปลงข้อมูล FoldingFeature เป็นสถานะที่แอปอ่านได้ FoldingFeatureAdapter ทำให้พิกัดบานพับเป็นมาตรฐานและกำหนดว่าท่าทางปัจจุบันคือ HALF_OPENED, FLAT หรือ TABLE_TOP ซึ่งช่วยนักพัฒนาให้ไม่ต้องคำนวณมุมและเกณฑ์ด้วยตนเอง
สำหรับแอป Compose WindowManager มี WindowSizeClass และตัวปรับแต่งที่คำนึงถึงการพับ คอมโพเนนต์ BoxWithConstraints ปรับให้เข้ากับการเปลี่ยนแปลงขนาดหน้าจอในเวลาจริงโดยไม่ต้องสร้าง Activity ใหม่ Compose จะเรียก recomposition โดยอัตโนมัติเมื่อ WindowMetrics เปลี่ยนไป
val windowManager = WindowManager(context)
val controller = windowManager.screenContinuityController
controller.registerContinuityListener { feature: FoldingFeature ->
when (feature.state) {
FoldingFeature.State.HALF_OPENED -> enterTabletopMode()
FoldingFeature.State.FLAT -> expandToTablet()
}
}
มาดูตัวอย่าง Activity ที่สมบูรณ์พร้อมการสนับสนุน Screen Continuity MainActivity จัดการสามสถานการณ์: การพับ การกาง และสถานะพับครึ่ง ข้อมูลถูกบันทึกผ่าน onRetainNonConfigurationInstance และกู้คืนเมื่อสร้างใหม่
class ContinuityActivity : AppCompatActivity() {
private lateinit var binding: ActivityContinuityBinding
private var itemList = mutableListOf<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityContinuityBinding.inflate(layoutInflater)
setContentView(binding.root)
val savedState = lastNonConfigurationInstance as? ContinuityState
if (savedState != null) {
itemList.addAll(savedState.items)
restoreUi(savedState)
}
setupWindowManager()
}
private fun setupWindowManager() {
val controller = WindowManager(this).screenContinuityController
controller.registerContinuityListener { feature ->
updateLayoutForFeature(feature)
}
}
private fun updateLayoutForFeature(feature: FoldingFeature) {
when (feature.state) {
FoldingFeature.State.HALF_OPENED -> binding.root.enableTabletopMode()
FoldingFeature.State.FLAT -> binding.root.enableTabletMode()
FoldingFeature.State.TABLE_TOP -> binding.root.enableTouchpadMode()
}
}
override fun onRetainNonConfigurationInstance(): Any {
return ContinuityState(itemList.toList(), binding.listView.firstVisiblePosition)
}
}
data class ContinuityState(
val items: List<String>,
val scrollPosition: Int
)
องค์ประกอบสำคัญคือคลาส ContinuityState ซึ่งเก็บรายการไอเท็มและตำแหน่งการเลื่อน Activity บันทึกก่อนสร้างใหม่และกู้คืนทันทีหลังจากเรียก onCreate ตัวควบคุม WindowManager สมัครรับการเปลี่ยนท่าทางและสลับเลย์เอาต์ระหว่างโหมด
Android Studio มีอีมูเลเตอร์อุปกรณ์พับได้ที่รองรับทั้งสามท่าทาง ในการทดสอบ Screen Continuity เพียงสร้างอุปกรณ์เสมือนประเภท Pixel Fold หรือ Samsung Galaxy Z Fold และเปลี่ยนท่าทางผ่านแผงควบคุมอีมูเลเตอร์
สร้าง AVD ด้วยหมวดหมู่ Foldable และเลือกความละเอียดหน้าจอ 7.6 นิ้ว ในส่วนควบคุมเพิ่มเติมของอีมูเลเตอร์ เปิดแท็บ Folding Postures และสลับระหว่างท่าทาง การสลับแต่ละครั้งจะเรียก configuration change ที่แอปควรจัดการอย่างถูกต้อง
บนอุปกรณ์จริง (Galaxy Z Fold 5, Pixel Fold) การทดสอบทำโดยการพับและกางทางกายภาพ Samsung DeX และ Multi-Window โหมดก็เปิดใช้งานความต่อเนื่องเช่นกัน สำหรับการดีบัก ใช้คำสั่ง ADB adb shell dumpsys window policy ซึ่งแสดงสถานะการพับปัจจุบัน
ข้อผิดพลาดหลักรวมถึงการสูญเสียสถานะ RecyclerView การรีเซ็ตเนื้อหาช่องข้อความ และการปิดหน้าต่างโต้ตอบ ViewModel แก้ปัญหาเหล่านี้โดยเก็บข้อมูลในหน่วยความจำโดยไม่ขึ้นกับวงจรชีวิตของ Activity การใส่คำอธิบายประกอบ Activity ใน manifest ด้วยพารามิเตอร์ android:configChanges ก็สำคัญเช่นกันหากแอปจัดการการเปลี่ยนแปลงด้วยตนเอง
<!-- AndroidManifest.xml -->
@android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
คำถามที่พบบ่อย
Screen Continuity บันทึกสถานะระหว่างการเปลี่ยนแปลงขนาดหน้าจอทางกายภาพ ไม่ใช่แค่เมื่อหมุน onSaveInstanceState ปกติไม่รับประกันการรักษาสถานะเมื่อเปลี่ยนท่าทางอุปกรณ์พับได้ ในขณะที่ ScreenContinuityController จัดการสถานการณ์เฉพาะนี้
อุปกรณ์พับได้ทั้งหมดที่ใช้ Android 10+ และ Google Play Services การรองรับรวมอยู่ใน Pixel Fold, ซีรีส์ Galaxy Z Fold, Huawei Mate X, Oppo Find N และ OnePlus Open ต้องใช้ Jetpack WindowManager เวอร์ชัน 1.1 ขึ้นไป
Jetpack Compose รองรับ Screen Continuity ผ่าน rememberSaveable และ WindowSizeClass องค์ประกอบตอบสนองต่อการเปลี่ยนแปลง WindowMetrics โดยอัตโนมัติ และ rememberSaveable รักษาสถานะระหว่างการ recomposition ตัวปรับแต่ง onSizeChanged ช่วยให้ติดตามการเปลี่ยนแปลงขนาดในเวลาจริง
เมื่อกางหรือพับอุปกรณ์ Activity จะถูกสร้างใหม่โดยไม่บันทึกสถานะ ผู้ใช้สูญเสียข้อมูลที่ป้อน การเลื่อนถูกรีเซ็ต และกล่องโต้ตอบที่เปิดอยู่ถูกปิด นี่นำไปสู่รีวิวเชิงลบและการให้คะแนนแอปที่ต่ำลงใน Google Play
Android Emulator รองรับการจำลองอุปกรณ์พับได้ สร้าง AVD ประเภท Pixel Fold เปิด Extended Controls และเลือกแท็บ Folding Postures การเปลี่ยนท่าทางจะเรียก configuration change ทำให้คุณสามารถทดสอบการรักษาสถานะโดยไม่ต้องใช้อุปกรณ์จริง
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ