Apps foundation

การปรับขนาดการโต้ตอบด้วยอินพุตที่นอกเหนือจากหน้าจอสัมผัสด้วย Jetpack Compose

ลำโพง

  • Alex Vanyo

    วิศวกรซอฟต์แวร์

  • Jeremy Walker

    วิศวกรซอฟต์แวร์ของ Compose

เกี่ยวกับ

เกี่ยวกับการเสวนา

เมื่อรูปแบบของอุปกรณ์ใหม่ๆ มีมากกว่าหน้าจอสัมผัส ระบบอินพุตของ Compose จึงได้รับการพัฒนาเพื่อตอบสนองความท้าทายนี้ สถาปัตยกรรมแบบเลเยอร์เป็นรากฐานที่รองรับทุกอย่างตั้งแต่ท่าทางสัมผัสแทร็กแพดขั้นสูงไปจนถึงอินพุตฮาร์ดแวร์แบบใหม่ได้อย่างราบรื่น

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

สรุป

  • Jetpack Compose จะประมวลผลเหตุการณ์ตัวชี้ Android ที่เข้ามาผ่านไปป์ไลน์ 6 ระยะ ไปป์ไลน์นี้จะรักษาแผนผังเส้นทางการแตะและส่งเหตุการณ์ในการส่งผ่าน 3 ครั้งในโหนด UI
  • ตอนนี้อินพุตแทร็กแพดใน Compose จะแมปกับเหตุการณ์เมาส์แทนการสัมผัส นอกจากนี้ Compose ยังแปลงเหตุการณ์การใช้นิ้วจำลองของแพลตฟอร์มเป็นเหตุการณ์ตัวชี้การเลื่อนและการปรับขนาดโดยเฉพาะด้วย
  • แทร็กแพดของแว่นตาอัจฉริยะจะใช้ประเภทอินพุตทางอ้อมแทนการแตะพิกัดบนหน้าจอ โดยใช้แกนการเคลื่อนไหวตามทิศทางหลักเพื่อแมปการปัดแนวนอนเป็นการไปยังส่วนถัดไปหรือก่อนหน้าในแนวตั้ง
  • การรองรับการทดสอบได้ขยายออกไปนอกเหนือจากการแตะด้วยวิธีการใหม่ๆ เช่น performTrackpadInput API เหล่านี้มีแพลตฟอร์มการทดสอบที่คุ้นเคยเพื่อตรวจสอบว่าแอปจัดการอุปกรณ์ที่ไม่ใช่ระบบสัมผัสได้อย่างถูกต้อง

Gemini Notebook

หัวข้อ

  • jetpack-compose
  • pointer-input
  • แทร็กแพด
  • ท่าทางสัมผัส
  • intelligent-eyewear
  • การช่วยเหลือพิเศษ

ข้อความถอดเสียง

ข้อมูลเบื้องต้นและปรัชญาการป้อนข้อมูล

  • สวัสดีทุกคน

  • หวังว่าคุณจะได้รับประสบการณ์ที่ดีในงาน Android Developer Summit และขอขอบคุณที่เข้าร่วมการบรรยายของเรา

  • ผม Alex Vanyo วิศวกรซอฟต์แวร์ในทีม Compose และ Jeremy ซึ่งเป็นวิศวกรซอฟต์แวร์ในทีม Compose เช่นกัน

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

  • โดยกว้างๆ แล้ว อินพุตจะบันทึกวิธีที่ผู้ใช้โต้ตอบกับแอปของคุณ

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

  • อินพุตประเภทอื่นๆ ได้แก่ แป้นพิมพ์จริง เมาส์ แทร็กแพด สไตลัส คอนโทรลเลอร์ และอุปกรณ์แบบหมุน

  • นอกจากนี้ เรายังเห็นอินพุตประเภทใหม่ๆ ด้วย เช่น แทร็กแพดบนแว่นตาอัจฉริยะ การติดตามการเคลื่อนไหวของดวงตาและการติดตามการเคลื่อนไหวของมือใน XR รวมถึงการเคลื่อนไหวนิ้วและการเคลื่อนไหวข้อมือใน Wear

  • และหากต้องการดูข้อมูลทั่วไปเพิ่มเติม ก็ยังมีอินพุตประเภทอื่นๆ ด้วย เช่น IME ของซอฟต์แวร์สำหรับเครื่องมือแก้ไขข้อความ ไมโครโฟน กล้อง และเซ็นเซอร์อื่นๆ ของอุปกรณ์

  • คุณต้องคาดหวังว่าแอปของคุณจะถูกใช้กับอินพุตประเภทต่างๆ มากมาย

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

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

  • แม้ว่า Chromebook จะมีแทร็กแพดและแป้นพิมพ์ในตัว แต่ก็ไม่ได้ทำให้ประเภทอินพุตเหล่านั้นเป็นเอกลักษณ์เฉพาะสำหรับรูปแบบของอุปกรณ์ดังกล่าว

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

  • เหตุผลสำคัญประการที่ 2 ที่ควรคาดหวังและรองรับอินพุตหลายประเภทคือการช่วยเหลือพิเศษ

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

  • และอาจมีข้อกำหนดทางกฎหมายให้มีลักษณะการทำงานที่เฉพาะเจาะจงและเข้ากันได้ในแอปพลิเคชันสำหรับอินพุตประเภทเหล่านี้ โดยเฉพาะอย่างยิ่งเกี่ยวกับสิ่งต่างๆ เช่น แป้นพิมพ์และเมาส์ ทั้งนี้ขึ้นอยู่กับเขตอำนาจศาล

  • กล่าวโดยย่อคือ คุณควรสร้างการรองรับอินพุตประเภทต่างๆ ไม่ว่าจะเป็นอุปกรณ์รูปแบบใดก็ตาม

  • มาดูกันว่า Jetpack Compose ช่วยให้แอปของคุณตอบสนองความต้องการของผู้ใช้เหล่านี้ได้อย่างไร

  • โดยทั่วไปแล้ว ปรัชญาของ Compose คือประเภทอินพุตที่แตกต่างกันเหล่านี้ควรทำงานอย่างเหมาะสมตั้งแต่แกะกล่องด้วยคอมโพเนนต์มาตรฐานโดยที่คุณไม่ต้องทำอะไรเป็นพิเศษ

  • จากนั้น คุณควรมีเครื่องมือที่จำเป็นในการปรับแต่งและปรับเปลี่ยนลักษณะการทำงานตามที่เห็นสมควร

  • ดังนั้น นอกเหนือจากประเภทอินพุตเริ่มต้นเหล่านั้นแล้ว เมื่อแพลตฟอร์มที่เกี่ยวข้องรองรับประเภทอินพุตมากขึ้น เราจึงตั้งเป้าที่จะสร้างการรองรับประเภทอินพุตเหล่านั้นในคอมโพเนนต์ Compose ซึ่งจะช่วยปรับปรุงลักษณะการทำงานของแอปพลิเคชันได้เพียงแค่อัปเดตเวอร์ชันของ Compose

  • เราจะมาดูตัวอย่าง 2 รายการในการพูดคุยครั้งนี้ ซึ่งทั้ง 2 รายการเป็นส่วนเสริมล่าสุดของ Compose

  • ทั้ง 2 อย่างนี้เป็นอุปกรณ์ที่คล้ายกับแทร็กแพด แต่คุณจะเห็นว่ามีการใช้งานที่แตกต่างกันมาก

  • เรามาเริ่มกันที่งานล่าสุดเกี่ยวกับแทร็กแพดของแล็ปท็อปประเภทต่างๆ

  • แทร็กแพดเป็นอุปกรณ์อินพุตที่ใช้ตัวชี้

  • กล่าวอย่างเจาะจงคือ เมื่อใช้แทร็กแพด คุณจะได้พิกัด 2 มิติ

  • แต่พิกัดของนิ้วบนแทร็กแพดจะไม่ได้อยู่ในพื้นที่พิกัดของ UI โดยตรงเหมือนกับหน้าจอสัมผัส

  • แต่สำหรับแทร็กแพดที่เหมือนแล็ปท็อป จะมีการแปลเป็นการควบคุมเคอร์เซอร์

  • ในการแปลนี้ คุณจะเห็นการแปลงแพลตฟอร์มที่ซับซ้อนมากมาย เช่น การเร่งความเร็วเคอร์เซอร์และการปฏิเสธฝ่ามือ

  • ดังนั้น สิ่งที่คุณจะได้รับในฝั่ง Compose คือตัวชี้ที่สอดคล้องกับตำแหน่งเคอร์เซอร์ซึ่งโดยปกติจะทำหน้าที่เหมือนอินพุตจากเมาส์

  • จากแพลตฟอร์ม Android เราจะได้รับข้อมูลการวางเมาส์เหนือ การคลิก รวมถึงการคลิกครั้งที่ 2 หรือ 3 และข้อมูลทั้งหมดนี้จะรวมอยู่ใน MotionEvent

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

การจัดการอินพุตตัวชี้ 6 ระยะ

  • เราจะแบ่งออกเป็น 6 ระยะ และจะอธิบายแต่ละระยะตามลำดับ

  • ระยะแรกคือการย้าย MotionEvent ไปยัง Compose

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

  • ดังนั้นใน Compose หมายความว่า Compose ซึ่งอยู่ในหน้าต่างปกติภายในกิจกรรมปกติจะได้รับ MotionEvent ซึ่งเป็น MotionEvent ของแพลตฟอร์ม Android

  • จากนั้น Compose จะต้องจัดการเหตุการณ์เหล่านั้นและทำทุกอย่างที่คุณต้องการทำภายใน Compose เกี่ยวกับอินพุตเคอร์เซอร์

  • ระยะแรกคือการแปล MotionEvent เหล่านั้นเป็นการแสดงผลภายในที่ไม่ขึ้นอยู่กับแพลตฟอร์มใน Compose ซึ่งเราเรียกว่า PointerInputEvent

  • ซึ่งเป็นประเภทภายใน คุณจึงจะไม่เห็นโดยตรง

  • และหากต้องการดูรายละเอียดทั้งหมดของสิ่งที่เกิดขึ้นที่นี่ คุณสามารถดู MotionEventAdapter ได้ แต่เราจะข้ามรายละเอียดเหล่านั้นไป

  • ตอนนี้เราจึงมีตัวแทนของ MotionEvent ใน Compose ที่ไม่ขึ้นอยู่กับแพลตฟอร์ม

  • ถัดไป ปรากฏว่าข้อมูลที่ป้อนมักจะเกิดขึ้นเมื่อเวลาผ่านไป

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

  • สิ่งต่างๆ เช่น ท่าทางสัมผัส การติดตามความเร็ว การตรวจจับการเลื่อน ทั้งหมดนี้ต้องอาศัยความเข้าใจเกี่ยวกับสิ่งที่เกิดขึ้นในแต่ละช่วงเวลา

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

  • ในโค้ด คุณสามารถมองว่านี่เป็นการนำ PointerInputEvent ปัจจุบันมารวมกับสิ่งที่เกิดขึ้นกับเหตุการณ์ก่อนหน้า จากนั้นเราจะสร้าง InternalPointerEvent ที่คำนึงถึงเวลา

  • นี่เป็นประเภทภายในอีกประเภทหนึ่งตามที่ชื่อบอกไว้ แต่คุณสามารถคิดว่านี่เป็นแผนที่ของรหัสตัวชี้ต่างๆ สำหรับการเปลี่ยนแปลง PointerInputChanges และ PointerInputChanges เป็นประเภทสาธารณะ

  • นี่คือรายการแรก

  • และสิ่งที่คุณอาจสังเกตเห็นเมื่อนึกถึงรหัสตัวชี้ต่างๆ ก็คือตอนนี้เราทราบถึงการติดตามเวลาแล้ว เราจึงติดตามได้ด้วยว่ารหัสตัวชี้จะมาและไปเมื่อใด

  • ไม่ได้มีแค่คนเดียว

  • หากคุณใช้นิ้วหลายนิ้วบนหน้าจอสัมผัส คุณอาจมีตัวชี้หลายตัวที่ปรากฏขึ้นและหายไปพร้อมกัน และเราต้องจัดการกับตัวชี้เหล่านั้น

  • ขอย้ำอีกครั้งว่าหากต้องการเจาะลึกรายละเอียด คุณสามารถดู PointerInputChangeEventProducer ซึ่งทำสิ่งเหล่านี้ทั้งหมด แต่เราจะข้ามไป

  • เรายังมีเรื่องที่ต้องพูดถึงอีกมาก

  • ตอนนี้เราจึงมีอินพุตที่แสดงถึง Compose และมีข้อมูลเวลา

  • ขั้นตอนถัดไปคือการพิจารณาว่าจะทำอย่างไรกับเหตุการณ์นั้น

  • เราจะส่งไปที่ไหน

  • ซึ่งนำไปสู่การทดสอบเส้นทาง Hit

  • ลองจินตนาการถึงสถานการณ์ที่เรามี MotionEvent ที่ส่งผ่าน และ ComposeView นี้กำลังเติมเต็มทั้งหน้าต่างหรือทั้งหน้าจอ

  • เราต้องทราบว่าจะส่งไปที่ใด

  • และเนื่องจาก Compose เป็นเพียงมุมมอง แต่เรามีสิ่งต่างๆ มากมายภายใน Compose ไม่ว่าจะเป็นโหนด ปุ่ม และสิ่งต่างๆ ที่คุณโต้ตอบด้วย เราจึงต้องดำเนินการทั้งหมดใน Compose เพื่อค้นหาว่าจะส่งเหตุการณ์ที่เกิดขึ้นในตำแหน่งที่เฉพาะเจาะจงไปที่ใด และค้นหาว่าโหนดใดที่สนใจเหตุการณ์นั้นจริงๆ

  • โหนดเลย์เอาต์เหล่านี้มีพิกัด มีขอบเขต และมีรูปร่าง ดังนั้นเราจึงต้องพิจารณาว่าโหนดใด (หากมี) ที่ถูกกด

  • แต่นั่นก็ไม่ใช่มุมมองที่พบบ่อยที่สุด

  • ปรากฏว่าเราชอบใส่องค์ประกอบที่โต้ตอบได้ไว้ในองค์ประกอบที่โต้ตอบได้อื่นๆ เช่น การใส่ปุ่มไว้ในรายการ

  • ซึ่งเราทำแบบนั้นบ่อยมาก

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

  • ดังนั้น ในกรณีนี้จึงมี 3 รายการตามลำดับชั้นที่ซ้อนกัน

  • เราจึงมีเส้นทาง Hit แต่ก็ยังไม่เพียงพอ

  • จำได้ไหมที่ผมบอกว่าเรามีเหตุการณ์อินพุตตัวชี้หลายรายการ ตัวชี้หลายตัวที่อาจกดลง

  • เราจำเป็นต้องมี Hit Path Tree แบบเต็ม

  • เมื่อมีตัวชี้หลายตัว เส้นทางการกดปุ่มจะไม่ได้มีเพียงเส้นทางเดียว

  • นั่นคือขั้นตอนถัดไป ซึ่งก็คือการสร้างและอัปเดต Hit Path Tree นี้

  • นี่คือข้อมูลโดยละเอียดเกี่ยวกับสิ่งที่เกิดขึ้น

  • ทางด้านซ้าย เรามีโหนดที่จัดวางเป็นภาพ และทางด้านซ้ายล่าง คุณจะเห็นการแสดงผลตามลำดับชั้น โหนดใดอยู่ภายในโหนดอื่นๆ โหนดใดเป็นบรรพบุรุษหรือลูกหลานของกันและกัน

  • เมื่อตัวชี้เลื่อนลง เราจะติดตาม Hit Path ซึ่งเป็นเส้นทางทั้งหมดผ่านโครงสร้าง จากนั้นเราจะได้รับ Hit Path สำหรับตัวชี้นั้นๆ

  • เส้นทางการตีนี้จะกลายเป็นต้นไม้เมื่อเราได้ตัวชี้ที่ 2

  • โดยอาจตัดกับโหนดเดียวกันกับอีกเส้นทางหนึ่ง แต่ก็อาจโต้ตอบกับโหนดอื่นๆ ด้วยเช่นกัน

  • ดังนั้น ทางด้านขวาคือ Hit Path Tree ที่เราดูแลรักษาอยู่ในปัจจุบัน

  • และพอยน์เตอร์อาจปรากฏขึ้นและหายไป ดังนั้นเราจึงต้องรักษาพอยน์เตอร์นี้ไว้ตลอดเวลาเพื่อให้แน่ใจว่าเราได้รับรายการโหนดทั้งหมดที่สนใจเหตุการณ์ที่กำลังดำเนินอยู่ทุกเหตุการณ์ ณ ขณะนี้

  • โอเค

  • ตอนนี้เรามี Hit Path Tree ที่เราดูแลรักษาสำหรับเหตุการณ์อินพุตเหล่านี้ ซึ่งหมายความว่าเรากำลังเข้าสู่ระยะถัดไป

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

  • เมื่อทราบแล้ว เราก็สามารถทำการแปลงพิกัดได้

  • ซึ่งจะดีมากหากโหนดได้รับเหตุการณ์อินพุตภายในพื้นที่พิกัดในเครื่องของตัวเอง คุณจึงไม่ต้องคำนวณพิกัดเองทั้งหมด

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

  • และนั่นคือสิ่งสุดท้ายในเฟสที่ 6 ซึ่งก็คือการส่งเหตุการณ์ออกไปในที่สุด

  • นี่คือเหตุการณ์อินพุตตัวชี้ที่เกิดขึ้น และส่งไปยังโหนดเพื่อดำเนินการตามที่ต้องการ

  • เราดำเนินการนี้ใน 3 ขั้นตอนที่แตกต่างกัน

  • เรามีบัตรผ่านเริ่มต้น บัตรผ่านหลัก และบัตรผ่านสุดท้าย

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

  • ดังนั้น การส่งผ่านครั้งแรกหรือการส่งผ่านเริ่มต้นจะส่งจากระดับบนลงล่าง

  • ตัวอย่างที่ฟีเจอร์นี้มีประโยชน์คือ หากโหนดเลย์เอาต์ด้านนอกบางโหนดอาจเป็นคอนเทนเนอร์การเลื่อน และโหนดทราบว่าได้เริ่มเลื่อนแล้ว และต้องการหยุดเหตุการณ์เคอร์เซอร์ทั้งหมดไม่ให้เข้าถึงโหนดย่อยใดๆ

  • ซึ่งในการส่งผ่านครั้งแรกจะทำให้สามารถใช้เหตุการณ์ได้ และองค์ประกอบย่อยจะไม่ได้รับเหตุการณ์ใดๆ อีก

  • บัตรที่ 2 คือบัตรหลัก

  • และนี่เป็นเพียงความสัมพันธ์เดียวที่เปลี่ยนจากผู้สืบทอดเป็นบรรพบุรุษ

  • ตามชื่อที่บอกไว้ บัตรนี้เป็นบัตรหลักสำหรับทำสิ่งต่างๆ

  • ตัวอย่างเช่น นี่คือตำแหน่งที่องค์ประกอบสืบทอดจะใช้เหตุการณ์การกดลง เริ่มจัดการการคลิก และมีโอกาสทำเช่นนั้นก่อนองค์ประกอบหลักหากคุณมีองค์ประกอบที่คลิกได้ที่ซ้อนกัน

  • และรอบสุดท้ายซึ่งเป็นรอบสุดท้ายจะมีลักษณะเหมือนกับรอบแรก โดยจะเริ่มจากระดับบนสุดไปยังระดับล่างสุด

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

  • ดังนั้น หากคอมโพเนนต์ย่อยเริ่มจัดการการคลิก แต่คอมโพเนนต์หลักเริ่มเลื่อน คอมโพเนนต์ย่อยจะเห็นว่าคอมโพเนนต์หลักทำเช่นนั้น แล้วคอมโพเนนต์ย่อยจะยกเลิกการคลิกที่เริ่มจัดการได้

  • ทั้งหมดนี้คือ 3 รอบและ 6 ระยะ

  • ซึ่งเป็นรากฐานสำหรับทุกอย่างที่อยู่เหนือระบบอินพุตตัวชี้

  • การจัดการท่าทางสัมผัสทั้งหมด การเลื่อน การลากได้ การคลิก และอินพุตเคอร์เซอร์ที่กำหนดเองทั้งหมดสร้างขึ้นจากรากฐานนี้

การอัปเดตแทร็กแพดและท่าทางสัมผัสแบบหลายนิ้ว

  • จากที่กล่าวมาทั้งหมด ตอนนี้เราจะพูดถึงรายละเอียดเล็กน้อยเกี่ยวกับวิธีที่เราปรับปรุงการรองรับลักษณะการทำงานของแทร็กแพดใน Compose

  • ดังนั้นก่อน Compose 1.12 ระบบจะรายงานเหตุการณ์การป้อนข้อมูลจากแทร็กแพดเป็นประเภทตัวชี้ของการแตะ เนื่องจากเป็นการใช้นิ้วโต้ตอบกับแทร็กแพดเพื่อควบคุมเคอร์เซอร์

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

  • เราจึงเปลี่ยนประเภทตัวชี้จาก PointerType.Touch เป็น PointerType.Mouse

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

  • ตัวอย่างเช่น ลักษณะการทำงานของเคล็ดลับเครื่องมือ คุณอาจต้องการให้แทร็กแพดและเมาส์มีลักษณะการทำงานเหมือนกันสำหรับเคล็ดลับเครื่องมือ

  • การเปลี่ยนแปลงครั้งใหญ่ครั้งที่ 2 ที่เราทำเกี่ยวกับแทร็กแพดเกี่ยวข้องกับท่าทางสัมผัสแบบหลายนิ้วที่คุณจะทำบนแทร็กแพด

  • ก่อนหน้านี้ Compose ได้ผ่านแนวคิดที่ชาญฉลาดแต่ค่อนข้างน่ากลัวเกี่ยวกับนิ้วปลอมของแพลตฟอร์ม Android

  • มาดูกันว่าหมายความว่าอย่างไร

  • เมื่อคุณใช้ 2 นิ้วบนแทร็กแพดเพื่อเลื่อน Android จะสร้างนิ้วจำลองบนหน้าจอสัมผัส 1 นิ้วซึ่งจะแตะลงตรงตำแหน่งเคอร์เซอร์

  • จากนั้น เมื่อคุณขยับนิ้วบนแทร็กแพด นิ้วจำลองบนหน้าจอสัมผัสจะขยับตามระยะทางและทิศทางที่ถูกต้องเพื่อเลียนแบบลักษณะการทำงานที่ต้องการ แล้วจึงปล่อย

  • ดังนั้น การเลื่อน 2 นิ้วขึ้นบนแทร็กแพดจะได้รับการแปลเป็นนิ้วปลอม 1 นิ้วบนหน้าจอสัมผัส ซึ่งเลื่อนขึ้นด้วยเช่นกัน ซึ่งจะทำให้เกิดการเลื่อนลง

  • สิ่งที่น่าสนใจคือ หากคุณใช้ฟีเจอร์การเลื่อนแทร็กแพดแบบย้อนกลับเหมือนฉัน คุณก็คงต้องการให้การเลื่อนไปในทิศทางตรงกันข้ามจริงๆ

  • และวิธีที่ทำได้คือการพลิกทิศทางของนิ้วปลอม

  • ดังนั้นตอนนี้ การใช้ 2 นิ้วบนแทร็กแพดที่เลื่อนขึ้นจะถูกแปลเป็นนิ้วปลอมนิ้วเดียวบนหน้าจอสัมผัสที่เลื่อนลง ซึ่งจะทำให้เกิดการเลื่อนขึ้น ซึ่งตรงกันข้ามกับสิ่งที่เรามีก่อนหน้านี้

  • การปรับขนาดก็ทำงานในลักษณะที่คล้ายกัน

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

  • ดังนั้น ตั้งแต่ Compose 1.12 สำหรับการเลื่อน และ Compose 1.13 สำหรับการปรับขนาด ตอนนี้เราจะสกัดกั้นนิ้วปลอมเหล่านั้น

  • เราจะไม่ส่งเหตุการณ์เหล่านั้นผ่านแพลตฟอร์มที่ให้มา แต่จะตีความเหตุการณ์เหล่านั้นใหม่เป็นประเภทเหตุการณ์ตัวชี้ใหม่ ได้แก่ PanStart, PanMove และ PanEnd สำหรับการแพน และ ScaleStart, ScaleChange และ ScaleEnd สำหรับการปรับขนาด

  • และเราจะทำเช่นนี้ในระยะการแปลงเหตุการณ์ Android เป็น Compose ที่ฉันพูดถึงก่อนหน้านี้

  • ดังนั้น เราจึงแปลงเหตุการณ์ Fake Finger เป็นประเภทที่เหมาะสม แล้วส่งผ่านท่าทางสัมผัสที่แพลตฟอร์มกำหนดนี้ไปยัง Hit Path ที่สอดคล้องกับเคอร์เซอร์

  • มาดูกันว่าทำไมเรื่องนี้จึงสำคัญ

  • ทำไมเราจึงทำเช่นนี้

  • สมมติว่ากล่องนี้เป็นรูปภาพสวยๆ ที่เราต้องการปรับขนาดให้ใหญ่ขึ้น

  • เมื่อคุณใช้ 2 นิ้วบนแทร็กแพดเพื่อปรับขนาด เป็นไปได้ว่านิ้วปลอมนิ้วใดนิ้วหนึ่งอาจไม่โดนองค์ประกอบ

  • เส้นทางการกดแป้นจะไม่ตัดกับรูปภาพ และจะเริ่มต้นนอกขอบเขต

  • ดังนั้น สิ่งที่จะเกิดขึ้นแทนการปรับขนาดคือรูปภาพอาจเลื่อนแทน

  • จากนั้นหากมีองค์ประกอบที่เลื่อนได้อีกรายการหนึ่งอยู่นอกรูปภาพ องค์ประกอบนั้นก็อาจเริ่มเลื่อนไปพร้อมกันด้วย

  • ซึ่งไม่ใช่สิ่งที่ผู้ใช้ต้องการ

  • บริษัทต้องการขยายธุรกิจ

  • ดังนั้น สิ่งที่เราทำในตอนนี้คือแทนที่จะส่งผ่านนิ้วปลอมเหล่านั้น ตอนนี้เราจะส่งท่าทางการปรับขนาดไปยังองค์ประกอบที่อยู่ใต้ตำแหน่งเคอร์เซอร์เท่านั้น ซึ่งจะนำไปสู่ลักษณะการทำงานที่ถูกต้อง

  • ไม่ว่าเคอร์เซอร์จะอยู่ที่ใดหรืออยู่ใกล้กับขอบขององค์ประกอบที่ต้องการปรับขนาดมากเพียงใด ตอนนี้องค์ประกอบจะปรับขนาดได้อย่างถูกต้อง

  • ข่าวดีสำหรับทุกคนก็คือ ระบบจะใช้เหตุการณ์อินพุตที่ตีความใหม่เหล่านี้โดยค่าเริ่มต้นในคอมโพเนนต์ต่างๆ เช่น scrollable และ transformable เพื่อให้พฤติกรรมที่มีคุณภาพสูงขึ้นสำหรับอินพุตแทร็กแพด หากคุณใช้บล็อกพื้นฐานเหล่านั้น

  • และหากคุณใช้สิ่งที่สร้างขึ้นจาก API เหล่านี้ คุณจะได้รับลักษณะการทำงานที่ปรับปรุงแล้วเพียงแค่อัปเดต Compose เป็นเวอร์ชันล่าสุด

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

  • และแน่นอนว่าเรายังเพิ่ม API การทดสอบด้วย ซึ่งคุณสามารถตรวจสอบได้ว่าแอปของคุณจัดการอินพุตประเภทต่างๆ เหล่านี้อย่างถูกต้องหรือไม่

  • ดังนั้น performTrackpadInput จึงดูคล้ายกับ API การทดสอบที่มีอยู่สำหรับเมาส์และการสัมผัสอย่างมาก

    onNodeWithContentDescription("Photo")
        .performTrackpadInput {
            click(center)
    
            pan(Offset(0f, 100f))
    
            scale(0.9f)
        }
  • และเมื่อใช้ทั้งหมดนี้ คุณจะตรวจสอบได้ว่าแอปทำงานอย่างถูกต้องไม่ว่าผู้ใช้จะใช้อุปกรณ์อินพุตใดในอุปกรณ์ของคุณ

  • หวังว่าข้อมูลนี้จะช่วยให้คุณเข้าใจได้ดียิ่งขึ้นว่าเหตุการณ์เคอร์เซอร์ทำงานอย่างไรตั้งแต่การใช้นิ้วแตะทัชแพดไปจนถึงการทำงานในแอป

  • ต่อไปฉันจะส่งต่อให้ Jeremy พูดถึงวิธีที่แตกต่างออกไปอย่างมากในการใช้แทร็กแพด

ข้อมูลเบื้องต้นเกี่ยวกับการป้อนข้อมูลโดยอ้อม

  • ขอขอบคุณ

  • โอเค

  • สวัสดี ฉันชื่อ Jeremy Walker

  • ฉันทำงานเกี่ยวกับอินพุตเป็นจำนวนมาก และคิดว่าน่าสนใจหากจะบอกคุณเกี่ยวกับสิ่งใหม่ๆ ที่เรากำลังทำกับอินพุต Compose และผลกระทบที่มีต่อคุณ

  • และโดยเฉพาะอย่างยิ่งกับอินพุตประเภททางอ้อมนี้ ซึ่งเกิดขึ้นเนื่องจากอินพุตใหม่ที่อิงตามรูปแบบของอุปกรณ์ใหม่ นั่นคือแว่นตาอัจฉริยะ

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

  • ซึ่งแตกต่างจากที่ Alex พูดถึงเล็กน้อยตรงที่อยู่ด้านข้างของศีรษะ เป็นแนวตั้ง กว้างมาก และสั้นมาก

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

  • แล้วเราจะรองรับการใช้งานอย่างไร

  • นี่คือหน้าตาของ UI ของแว่นตา

  • โดยได้รับการออกแบบมาเป็นพิเศษเพื่อวางเนื้อหาให้กลมกลืนกับขอบเขตการมองเห็นของคุณ

  • แต่ก็เป็นเรื่องง่ายๆ เราพยายามทำให้เข้าใจง่าย

  • และหากดูตัวอย่างที่นี่ คุณจะเห็นว่านี่คือรายการ

  • โดยเน้นที่องค์ประกอบบางอย่างตรงกลาง

  • เราต้องการทำอะไรกันแน่

  • เราต้องการเลือก หรืออาจย้ายไปยังรายการก่อนหน้าหรือถัดไป

  • เราไม่จำเป็นต้องทราบตำแหน่งของหน้าจอ

  • และตัวเลือกนี้จะซับซ้อนขึ้นมาอีกนิด แต่คุณจะเห็นว่ามีตัวเลือกพื้นฐาน 3 อย่าง ได้แก่ วางสาย เปิดเสียง หรือปิดวิดีโอ

  • แต่จริงๆ แล้ว คุณต้องการเลือกรายการนั้น หรือย้ายไปยังรายการอื่นแล้วเลือกรายการนั้น

  • เราจึงคิดว่าไม่จำเป็นต้องแมปกับตำแหน่งบนหน้าจอโดยตรง หรือในกรณีนี้คือดวงตาของคุณ

  • นี่คือหน้าตาของฟีเจอร์นี้

  • ตัวอย่างเช่น คุณจะเห็นได้ที่นี่ว่าฉันกำลังเลื่อนไปมาระหว่างองค์ประกอบต่างๆ และนี่คือ UI ของแว่นตา ซึ่งตรงกับสิ่งที่เราต้องการ

  • และคุณสามารถแตะบัตรนั้นได้

  • เราจึงพิจารณา Android เพื่อดูว่ามีอะไรบ้างที่เราสามารถใช้เพื่อรองรับการทำงานนี้ได้

  • และถ้าคุณเคยได้รับ โอ้ ขอโทษที

  • ซึ่งเป็นการข้ามไปข้างหน้า

  • ขอย้อนกลับไปก่อน

  • เริ่มเลยนะคะ

  • โอเค

  • ดังนั้น หากคุณเคยใช้อุปกรณ์เหล่านี้และลิงก์กับอุปกรณ์ Android คุณจะทราบว่าสามารถย้ายจากองค์ประกอบ UI หนึ่งไปยังอีกองค์ประกอบหนึ่งได้อย่างง่ายดาย

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

  • หากมีเมนูเกมและมีคอนโทรลเลอร์นี้ คุณสามารถใช้ D-pad หรือจอยสติ๊กเพื่อไปยังองค์ประกอบ UI เช่น ในเมนู แล้วเลือกองค์ประกอบนั้น

  • แป้นพิมพ์ก็เช่นกัน

  • ซึ่งตรงกับสิ่งที่เราต้องการใน Compose

  • และนี่คือตัวอย่างเพื่อให้คุณเห็นภาพว่าหน้าตาเป็นอย่างไร

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

  • และแนวคิดก็คือพิกัด X และ Y จะไม่ถูกแตะต้องและไม่เชื่อมโยงกับหน้าจอเลย

  • แต่จะใช้เพื่อตรวจจับท่าทางสัมผัสเท่านั้น

  • สิ่งที่คุณทำได้คือ หากปัดไปทางขวา ก็จะเหมือนกับการกดชอบ ลูกศรจะเลื่อนไป

  • หากปัดไปทางซ้าย คุณจะไปทางซ้าย ขึ้น และลง

  • ดังนั้น วิธีนี้จึงช่วยให้เราได้สิ่งที่ต้องการเป็นส่วนใหญ่

  • คุณใช้เฉพาะ x และ y สำหรับการติดตามความเร็วเพื่อดูการลากและการปัด เป็นต้น ซึ่งจะช่วยให้เราได้ข้อมูลส่วนใหญ่ที่ต้องการเพื่อเริ่มต้นใช้งาน Compose

  • ซึ่งไม่ตรงกันทั้งหมดเพราะมีการแมปกับทีวีด้วย เราจึงต้องตรวจสอบว่าไม่ได้ใช้เส้นทางทีวีและไม่ทำให้ทีวีมีปัญหาในภายหลัง ดังนั้นเราจึงต้องแยกทั้ง 2 อย่างออกจากกัน แต่เราจะพูดถึงเรื่องนี้ในอีกสักครู่

  • แต่ก็ช่วยให้เรามีจุดเริ่มต้น

  • เพื่อให้เราใช้การไปยังส่วนต่างๆ ด้วยการสัมผัสประเภทนี้ได้

การออกแบบ API สำหรับการป้อนข้อมูลโดยอ้อมและรูปแบบของอุปกรณ์ใหม่ๆ

  • เอาล่ะ

  • การออกแบบ API จะมีลักษณะอย่างไร

  • ใน Compose อินพุตที่พบบ่อยที่สุดคือการแตะใช่ไหม

  • ดังนั้นเราจึงมีงานที่ต้องทำเกี่ยวกับเรื่องนี้มากมาย

  • เราจึงต้องหาวิธีที่ทำให้เนื้อหาเกี่ยวข้องกับเรื่องนั้น

  • โปรดทราบว่า PointerEvent มีลักษณะดังนี้

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

  • หากคุณพับนิ้วลง 3 นิ้ว คุณจะมี 3 รายการในลิสต์

  • เราจึงอยากให้มีลักษณะคล้ายกับแบบนี้

  • นี่ไม่ใช่โมดูล UI ซึ่งเป็นโมดูลที่ต่ำกว่าที่นักพัฒนาแอปส่วนใหญ่ใช้เมื่อจัดการกับอินพุต

  • โดยจะอยู่เหนือชั้นพื้นฐานขึ้นไปอีกชั้นหนึ่ง

  • และนั่นคือที่ที่ตัวตรวจจับท่าทางสัมผัสทั้งหมดของเราอยู่

  • เพราะในฐานะนักพัฒนาซอฟต์แวร์ คุณไม่จำเป็นต้องสนใจรายละเอียดเล็กๆ น้อยๆ เหล่านี้

  • คุณเพียงต้องการทราบว่ามีการลาก การคลิก หรือการปัดเกิดขึ้นหรือไม่ จากนั้นจึงดำเนินการตามนั้น

  • เราจึงมีโค้ดจำนวนมากที่ทำหน้าที่ดังกล่าวให้คุณ และโค้ดเหล่านี้ทำงานโดยใช้สิ่งต่างๆ เหล่านี้ในเบื้องหลัง

  • เราจึงเริ่มคิดว่าต้องทำให้โค้ดที่มีอยู่ในรากฐานสามารถรองรับประเภทใหม่เหล่านี้ได้อย่างง่ายดายที่สุด

  • เราจึงสร้างประเภทใหม่ที่มีลักษณะคล้ายกันมาก

  • แต่จะเรียกว่าการแทรกพรอมต์โดยอ้อม

  • ส่วนการโต้ตอบทางอ้อมหมายความว่าไม่ได้แตะหน้าจอโดยตรง

  • ดังนั้น ระบบจะแจ้งให้คุณทราบว่าฟีเจอร์นี้กำลังจะมา และอย่าคิดถึงฟีเจอร์นี้จากมุมมองของการแตะ

  • ลองนึกภาพว่าเรากำลังจัดการท่าทางสัมผัสและไปยังส่วนต่างๆ ระหว่างองค์ประกอบ UI

  • ประเภทเหมือนกัน

  • มีรายชื่อนิ้วอยู่

  • ในกรณีนี้คือ IndirectPointerInputChange

  • เราจึงทำตามนั้นและได้ผลดีมาก

  • แต่ยังมีอีกรายการหนึ่งที่เราพบซึ่งเรียกว่าแกนการเคลื่อนไหวตามทิศทางหลัก

  • ชื่ออาจจะยาวไปหน่อย แต่คุณจะเข้าใจเมื่อเราอธิบาย เพราะที่มาของชื่อนี้ค่อนข้างน่าสนใจ

  • แล้วฟีเจอร์นี้เกิดขึ้นได้อย่างไร

  • อีกครั้ง คุณมีทัชแพดนี้ที่ด้านข้างของศีรษะ ซึ่งมีลักษณะกว้างและสั้น

  • และในตอนนี้ เราก็มีแนวคิดที่ว่า เรามีการนำทางด้วยการสัมผัสแล้ว

  • เราจึงปัดไปทางซ้ายและขวาได้

  • ซึ่งก็ใช้ได้ดีเลย

  • แต่ถ้าคุณนึกถึงแทร็กแพดที่มีอยู่ในปัจจุบัน

  • เมื่อคุณเลื่อนไปทางซ้ายหรือขวา คุณจะเลื่อนไปทางซ้ายหรือขวาบนแทร็กแพดพร้อมกับเนื้อหา UI

  • หากเลื่อนขึ้นหรือลง คุณจะเลื่อนดูรายการขึ้นหรือลง

  • ดังนั้นหากคุณพยายามทำแบบนั้นโดยสวมแว่นตา แบบนี้ก็ไม่แย่เกินไปใช่ไหม

  • แต่ถ้าคุณทำแบบนี้ ประสบการณ์ที่ได้ก็จะไม่ดีนัก

  • เราพบว่าการเคลื่อนไหวที่เป็นธรรมชาติที่สุดคือการแตะ แต่เป็นการปัดไปตามด้านข้างของแว่นตา

  • เราจึงทำการศึกษาหลายอย่างกับผู้ใช้ และพบว่าจริงๆ แล้วผู้ใช้คาดหวังว่าเมื่อปัดในแนวนอน เนื้อหาจะไม่เลื่อนในแนวนอน แต่จะเลื่อนในแนวตั้ง

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

  • เราจึงนำอินพุต 2 มิติมาพยายามคิดแบบ 1 มิติ

  • และนั่นคือที่มาของแนวคิดเรื่องแกนการเคลื่อนไหวหลัก ซึ่งคุณสามารถเลื่อนในแนวนอนและจะเลื่อนในแนวตั้งได้

  • คุณจึงระบุในอุปกรณ์ได้

  • คุณอาจจะบอกว่า เฮ้ นี่ไม่ใช่แทร็กแพดธรรมดาๆ นะ

  • ฉันต้องการให้ทิศทางหลักเป็นแนวนอน และนั่นก็เป็นแกนหลักเพียงแกนเดียวที่ฉันต้องการเคลื่อนที่ไปตามนั้น

  • นั่นคือที่มาของชื่อนี้

  • ตกลง

  • เราจึงรู้สึกดีกับเรื่องนี้มาก

  • Compose จะจัดการทุกอย่างเอง

  • และคุณมีการใช้งานแนวตั้งที่ยอดเยี่ยมนี้

  • คุณลองพิจารณาเรื่องนี้ได้

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

  • เราไม่มีทิศทางขึ้น ลง ซ้าย ขวา

  • เรามีแค่ปุ่มไปข้างหน้าและย้อนกลับ

  • จากนั้นเราจะแมปได้หากคุณคุ้นเคยกับการโฟกัสด้วยถัดไปและก่อนหน้า

  • ตอนนี้เราก็แค่เลื่อนไปยังรายการถัดไปและก่อนหน้า

  • ซึ่งวิธีนี้ใช้ได้ดีกับวิดีโอแนวตั้ง

  • และยังดูดีขึ้นด้วย

  • ซึ่งใช้ได้กับวิดีโอแนวนอนทันทีที่แกะกล่องใช่ไหม

  • เพราะคุณมีรายการที่โฟกัสอยู่หลายรายการ

  • คุณเพียงแค่ไปที่รายการถัดไปหรือก่อนหน้า และจะใช้ได้กับทั้ง 2 รายการ

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

  • ดังนั้นตอนนี้เราจึงต้องนำแนวคิดนี้กลับไปที่แพลตฟอร์มและบอกว่า เราต้องกำหนดแนวคิดนี้ในแพลตฟอร์มเพื่อให้สามารถกำหนดมาตรฐานและอุปกรณ์เหล่านี้สามารถระบุได้เอง เพื่อให้ Compose รองรับได้อย่างเต็มที่

  • ดังนั้นจึงมีกรณีที่เราทำงานใน Compose และพัฒนาต่อไปใน Compose และทำงานย้อนกลับ และนำมาใช้ร่วมกัน

  • เราจึงทำตามนั้น

  • เราสร้าง API ใหม่นี้ขึ้นมาเพื่อให้คุณหรืออุปกรณ์สามารถระบุข้อมูลดังกล่าวได้

    InputDevice.ViewBehavior
    .getPrimaryDirectionalMotionAxis()
  • และหากคุณจำได้ก่อนหน้านี้ ตอนที่ฉันพูดถึงการป้อนข้อมูลด้วยการสัมผัสหรือการไปยังส่วนต่างๆ ด้วยการสัมผัส ฉันกำลังพูดถึงวิธีที่ออกแบบมาสำหรับทีวีเป็นหลัก

  • เราไม่ต้องการให้การติดตั้งใช้งานเหล่านั้นหยุดทำงาน

  • เราจึงเพิ่มอีกช่องหนึ่งเพื่อระบุอินพุตกระจกประเภทใหม่นี้

  • ตกลง

  • แล้วสุดท้ายแล้ว สิ่งนี้มีความหมายต่อคุณอย่างไร

  • นี่เป็นเวอร์ชันที่เจาะจงมากขึ้นของสิ่งที่คุณได้รับในฐานะเครื่องมือตรวจจับท่าทางสัมผัส

    // Glimmer Library
    Box(
        modifier =
            Modifier.fillMaxSize()
                .onIndirectPointerGesture(
                    enabled = true,
                    onSwipeForward = { /* onSwipeForward */ },
                    onSwipeBackward = { /* onSwipeBackward */ },
                    onClick = { /* onClick */ },
                )
                .focusTarget()
    ) {
        // App()
  • หากคุณใช้ Foundation อยู่แล้ว ระบบจะทำงานร่วมกับเครื่องมือตรวจจับท่าทางสัมผัสได้ทันที

  • เราได้ดำเนินการให้คุณแล้ว คุณจึงไม่ต้องทำอะไรเลย

  • แต่ถ้าคุณต้องการสร้างแอปสำหรับแว่นตา คุณสามารถใช้ไลบรารี Glimmer ของเราได้ และเรายังมีเครื่องมือตรวจจับท่าทางสัมผัสพิเศษ ซึ่งจะช่วยให้คุณไม่ต้องรวมท่าทางสัมผัสเข้าด้วยกัน คุณสามารถใช้เพียงท่าทางสัมผัสเดียวนี้เพื่อรับการคลิก เฟรมไปข้างหน้า และเฟรมย้อนกลับ

กำลังทดสอบอินพุตตัวชี้ทางอ้อม

  • ตกลง

  • เราได้พูดถึงการทำงานของ API ในแพลตฟอร์มและใน Compose ไปแล้ว

  • แล้วการทดสอบล่ะ

  • นี่คือลักษณะของการแตะเมื่อคุณต้องการทดสอบการแตะ

    @Test
    clickTest {
    
    rule.onNodeWithTag(defaultTag)
    .performTouchInput
    { click(center) }
    
    }
  • คุณแค่พูดว่า performTouchInput แล้วทำท่าทางสัมผัส

  • มีท่าทางสัมผัสที่แตกต่างกันมากมาย และเราสร้างเหตุการณ์เล็กๆ ทั้งหมดเพื่อทำให้ท่าทางสัมผัสเกิดขึ้น

  • การทำงานในระดับสูงเป็นอย่างไร

  • คุณมีโมดูล Compose UI, โมดูล UI Testing และโมดูลเหล่านี้จะสื่อสารกัน อย่างน้อยก็ในแง่ของอินพุต โดยใช้ MotionEvent

  • นอกจากนี้ โมดูลการทดสอบ UI ยังใช้กลไกการจัดคิว ซึ่งทั้งหมดอิงตาม MotionEvent

  • ทำไมเราจึงบอกคุณเรื่องนี้

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

  • แต่ฉันก็ทำได้

  • แล้วเรื่องนี้มีความหมายต่อคุณอย่างไร

  • หากคุณคุ้นเคยกับการทดสอบการป้อนข้อมูลด้วยการสัมผัส นี่คือสิ่งที่คุณจะได้รับสำหรับการป้อนข้อมูลทางอ้อม

  • คุณเพียงแค่เพิ่มคำว่า "ทางอ้อม" ลงในชื่อ

    @Test
    clickTest {
    
    rule.onNodeWithTag(defaultTag)
    // .performTouchInput
    .performIndirectPointerInput (
    IndirectPointerEventPrimaryDirectionalMotionAxis.X,
    inputDeviceSize,
    )
    { click(center) }
    }
  • ตอนนี้ฉันได้ส่งพารามิเตอร์เพิ่มเติมบางรายการแล้ว

  • คุณอาจคุ้นเคยกับส่วนแรก ซึ่งเป็นส่วนที่คุณระบุแนวนอน

  • และขนาดอินพุตก็จะเป็นขนาดของทัชแพดอย่างเห็นได้ชัด

  • ซึ่งการดำเนินการนี้ไม่ได้เปลี่ยนแปลงอะไรมากนัก

  • ดังนั้น หากดูซอร์สโค้ด คุณจะเห็นว่าฉันเพิ่งเขียนฟังก์ชันส่วนขยายและมีลักษณะดังนี้

    @Test
    clickTest {
    
    rule.onNodeWithTag(defaultTag)
    // .performTouchInput
    .performIndirectPointerInput
    { click(center) }
    
    }
  • ตกลง

  • ข้อมูลนี้จะช่วยให้คุณเห็นภาพงานทั้งหมดที่เราทำเพื่อรองรับแทร็กแพดบนกรอบแว่นหรือแว่นตาอัจฉริยะ

  • แต่เรากำลังทำสิ่งเหล่านี้อยู่ ฉันกำลังทำแบบฝึกหัดเหล่านี้สำหรับการติดตามการเคลื่อนไหวของดวงตาและการติดตามการเคลื่อนไหวของมือด้วย ดังนั้นจะมีอะไรอีกมากมายตามมา

  • และในภาพรวม สิ่งที่ผมอยากให้คุณจดจำจากส่วนของผมคืออะไร

สรุปและประเด็นสำคัญ

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

  • ดังนั้น หากคุณใช้ตัวตรวจจับท่าทางสัมผัสของ Foundation เหล่านี้ ก็จะใช้งานได้ทันที

  • นั่นคือข้อแรก

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

  • และแน่นอนว่าสำหรับการทดสอบ API เราต้องการรักษาอินเทอร์เฟซและรูปแบบที่คุ้นเคยไว้เพื่อให้คุณย้ายข้อมูลและทดสอบประเภทใหม่เหล่านี้ได้ง่ายที่สุด

  • ขอบคุณ หวังว่าข้อมูลนี้จะช่วยคุณได้

รหัส

ข้อมูลโค้ด

ข้อมูลโค้ด Kotlin ที่ 15:47 ใน "การอัปเดตแทร็กแพดและท่าทางสัมผัสแบบหลายนิ้ว"
onNodeWithContentDescription("Photo")
    .performTrackpadInput {
        click(center)

        pan(Offset(0f, 100f))

        scale(0.9f)
    }
ข้อมูลโค้ด Kotlin ที่ 25:08 ใน "การออกแบบ API สำหรับอินพุตทางอ้อมและรูปแบบของอุปกรณ์ใหม่"
InputDevice.ViewBehavior
.getPrimaryDirectionalMotionAxis()
ข้อมูลโค้ด Kotlin ที่ 25:32 ใน "การออกแบบ API สำหรับอินพุตทางอ้อมและรูปแบบของอุปกรณ์ใหม่"
// Glimmer Library
Box(
    modifier =
        Modifier.fillMaxSize()
            .onIndirectPointerGesture(
                enabled = true,
                onSwipeForward = { /* onSwipeForward */ },
                onSwipeBackward = { /* onSwipeBackward */ },
                onClick = { /* onClick */ },
            )
            .focusTarget()
) {
    // App()
ข้อมูลโค้ด Kotlin ที่นาที 26:11 ใน "การทดสอบอินพุตตัวชี้ทางอ้อม"
@Test
clickTest {

rule.onNodeWithTag(defaultTag)
.performTouchInput
{ click(center) }

}
ข้อมูลโค้ด Kotlin ที่นาที 27:08 ใน "การทดสอบอินพุตตัวชี้ทางอ้อม"
@Test
clickTest {

rule.onNodeWithTag(defaultTag)
// .performTouchInput
.performIndirectPointerInput (
IndirectPointerEventPrimaryDirectionalMotionAxis.X,
inputDeviceSize,
)
{ click(center) }
}
ข้อมูลโค้ด Kotlin ที่นาที 27:23 ใน "การทดสอบอินพุตตัวชี้ทางอ้อม"
@Test
clickTest {

rule.onNodeWithTag(defaultTag)
// .performTouchInput
.performIndirectPointerInput
{ click(center) }

}