การรองรับแป้นพิมพ์แบบถอดได้ช่วยเพิ่มประสิทธิภาพการทำงานของผู้ใช้ในอุปกรณ์หน้าจอขนาดใหญ่ได้สูงสุด Android จะทริกเกอร์การเปลี่ยนแปลงการกำหนดค่าทุกครั้งที่มีการต่อแป้นพิมพ์เข้ากับอุปกรณ์หรือถอดแป้นพิมพ์ออกจากอุปกรณ์ ซึ่งอาจทำให้สถานะ UI สูญหาย แอปของคุณสามารถบันทึกและกู้คืนสถานะ โดยให้ระบบจัดการการสร้างกิจกรรมใหม่ หรือจำกัดการสร้างกิจกรรมใหม่สำหรับการเปลี่ยนแปลงการกำหนดค่าแป้นพิมพ์
ในทุกกรณี ข้อมูลทั้งหมดที่เกี่ยวข้องกับแป้นพิมพ์จะจัดเก็บไว้ในออบเจ็กต์ Configuration ช่อง keyboard และ keyboardHidden ของออบเจ็กต์การกำหนดค่ามีข้อมูลเกี่ยวกับประเภทของแป้นพิมพ์และความพร้อมใช้งาน
แนวทางปฏิบัติแนะนำ
แอปที่เพิ่มประสิทธิภาพสำหรับหน้าจอขนาดใหญ่รองรับอุปกรณ์อินพุตทุกประเภท ตั้งแต่แป้นพิมพ์ซอฟต์แวร์และฮาร์ดแวร์ไปจนถึงสไตลัส เมาส์ แทร็กแพด และอุปกรณ์ต่อพ่วงอื่นๆ
การรองรับแป้นพิมพ์ภายนอกเกี่ยวข้องกับการเปลี่ยนแปลงการกำหนดค่า ซึ่งคุณสามารถจัดการได้ 2 วิธีดังนี้
- ปล่อยให้ระบบสร้างกิจกรรมที่กำลังทำงานอยู่ขึ้นมาใหม่ และคุณเป็นผู้จัดการสถานะของแอป
- จัดการการเปลี่ยนแปลงการกำหนดค่าด้วยตนเอง (ระบบจะไม่สร้างกิจกรรมขึ้นมาใหม่) โดยทำดังนี้
- ประกาศค่าการกำหนดค่าทั้งหมดที่เกี่ยวข้องกับแป้นพิมพ์
- สร้างเครื่องจัดการการเปลี่ยนแปลงการกำหนดค่า
แอปเพื่อการทำงานซึ่งมักต้องมีการควบคุม UI อย่างละเอียดสำหรับการป้อนข้อความและอินพุตอื่นๆ จะได้รับประโยชน์จากแนวทางแบบงาน DIY ในการจัดการการเปลี่ยนแปลงการกำหนดค่า
ในกรณีพิเศษ คุณอาจต้องการเปลี่ยนเลย์เอาต์ของแอปเมื่อมีการต่อหรือถอดแป้นพิมพ์ฮาร์ดแวร์ เช่น เพื่อเพิ่มพื้นที่สำหรับเครื่องมือหรือหน้าต่างแก้ไข
ใน Jetpack Compose คุณสามารถตอบสนองต่อการเปลี่ยนแปลงการกำหนดค่าแป้นพิมพ์ได้ 2 วิธีดังนี้
- UI แบบรีแอ็กทีฟ: อ่านสถานะการกำหนดค่าปัจจุบันโดยตรงใน Composable โดยใช้
LocalConfiguration.currentUI จะจัดองค์ประกอบใหม่โดยอัตโนมัติเพื่อปรับให้เข้ากับสถานะใหม่เมื่อต่อหรือถอดแป้นพิมพ์ - Callback ของผลข้างเคียง: ใช้
DisposableEffectที่รับรู้ถึงวงจรเพื่อลงทะเบียน Listener การเปลี่ยนแปลงการกำหนดค่าในกิจกรรมโฮสต์ ซึ่งช่วยให้คุณทริกเกอร์เหตุการณ์ที่ไม่ใช่ UI (เช่น การบันทึกหรือการวิเคราะห์) ได้โดยไม่ต้องสร้างกิจกรรมใหม่หรือสร้างอินสแตนซ์องค์ประกอบมุมมองจำลอง
ส่วนผสม
android:configChanges: แอตทริบิวต์ขององค์ประกอบ<activity>ในไฟล์ Manifest ของแอป แจ้งให้ระบบทราบเกี่ยวกับการเปลี่ยนแปลงการกำหนดค่าที่แอปจัดการLocalConfiguration: ผู้ให้บริการในพื้นที่ที่ประกอบกันได้ซึ่งแสดงConfigurationของอุปกรณ์ปัจจุบันDisposableEffect: API ผลข้างเคียงของ Compose ที่เรียกใช้บล็อกโค้ดเมื่อ Composable เข้าสู่ Composition และล้างข้อมูลเมื่อออกจาก Composition
ขั้นตอน
ประกาศแอตทริบิวต์ configChanges และเพิ่มค่าที่เกี่ยวข้องกับแป้นพิมพ์เพื่อป้องกันการสร้างกิจกรรมขึ้นมาใหม่ จากนั้นใช้ LocalConfiguration.current เพื่อปรับเลย์เอาต์ Composable แบบไดนามิก หรือลงทะเบียน Listener การกำหนดค่าโดยใช้ DisposableEffect
1. ประกาศแอตทริบิวต์ configChanges
อัปเดตองค์ประกอบ <activity> ในไฟล์ Manifest ของแอปโดยเพิ่มค่า keyboard|keyboardHidden ลงในรายการการเปลี่ยนแปลงการกำหนดค่าที่จัดการแล้ว ดังนี้
<activity
…
android:configChanges="...|keyboard|keyboardHidden">
2. ตอบสนองต่อการเปลี่ยนแปลงการกำหนดค่าแป้นพิมพ์
หากต้องการจัดการการเปลี่ยนแปลงการกำหนดค่าใน Jetpack Compose ให้ใช้ตัวเลือกใดตัวเลือกหนึ่งต่อไปนี้ โดยขึ้นอยู่กับว่าคุณกำลังอัปเดต UI หรือเรียกใช้ Callback ของผลข้างเคียง
ตัวเลือก ก: UI แบบรีแอ็กทีฟ (แนะนำ)
อ่านประเภทแป้นพิมพ์โดยตรงจาก
LocalConfiguration.currentเมื่อต่อหรือถอดแป้นพิมพ์ฮาร์ดแวร์ ค่านี้จะเปลี่ยนไป และ Compose จะจัดองค์ประกอบ UI ใหม่โดยอัตโนมัติval configuration = LocalConfiguration.current val isPhysicalKeyboardAttached = configuration.keyboard == Configuration.KEYBOARD_QWERTY if (isPhysicalKeyboardAttached) { // Render layout optimized for physical keyboard } else { // Render default layout }
ตัวเลือก ข: Side-Effect Listener
หากต้องการเรียกใช้ผลข้างเคียง (เช่น การบันทึก การอัปเดตฐานข้อมูลในเครื่อง หรือการเรียกใช้การวิเคราะห์) เมื่อการกำหนดค่ามีการเปลี่ยนแปลง ให้ใช้
DisposableEffectเพื่อลงทะเบียน Listener การเปลี่ยนแปลงการกำหนดค่าในโฮสต์ComponentActivityval context = LocalActivity.current DisposableEffect(context) { val activity = context as? ComponentActivity val listener = Consumer<Configuration> { newConfig -> val hasKeyboard = newConfig.keyboard == Configuration.KEYBOARD_QWERTY // Trigger non-UI actions, analytics, etc. } activity?.addOnConfigurationChangedListener(listener) onDispose { activity?.removeOnConfigurationChangedListener(listener) } }
ผลลัพธ์
ตอนนี้แอปของคุณจะตอบสนองต่อการต่อหรือถอดแป้นพิมพ์ภายนอกโดยไม่ต้องสร้างกิจกรรมที่กำลังทำงานอยู่ขึ้นมาใหม่
แหล่งข้อมูลเพิ่มเติม
ดูวิธีบันทึกสถานะ UI ของแอปในระหว่างการเปลี่ยนแปลงการกำหนดค่า เช่น การต่อหรือถอดแป้นพิมพ์ได้ที่บันทึกสถานะ UI