รองรับกล้องในอุปกรณ์หลายรูปแบบ

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

รูปที่ 1 ตัวอย่างแอปกล้องบนจอแสดงผลต่างๆ

เหตุผลที่ตรรกะของโทรศัพท์ใช้ไม่ได้

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

การวางแนวตามธรรมชาติ

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

การจัดแนวเซ็นเซอร์

  • สมมติฐาน: ขอบยาวของเซ็นเซอร์กล้องตรงกับขอบยาวของหน้าจอ
  • ความเป็นจริง: หน้าต่างที่ปรับขนาดได้อาจเป็นสี่เหลี่ยมจัตุรัสหรือแนวนอน ขณะที่เซ็นเซอร์จะยังคงคงที่ (โดยปกติคือ 4:3)
  • ผลลัพธ์: รูปภาพที่ยืดหรือบิดเบี้ยว
รูปที่ 3 ช่องมองภาพของกล้องก่อนและหลังใช้ค่าตัวคูณมาตราส่วนที่ถูกต้อง

ความหนาแน่นและขนาดของหน้าจอ

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

วิธีที่ 1: ใช้ Intent ของระบบ

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

การใช้ Intent ของระบบจะมอบหมายประสบการณ์การจับภาพทั้งหมดให้กับแอปกล้อง ที่พัฒนาโดยผู้ผลิตอุปกรณ์ดั้งเดิม (OEM) ของอุปกรณ์ ซึ่งเป็นการเอาต์ซอร์สความซับซ้อนของการรองรับรูปแบบอุปกรณ์อย่างมีประสิทธิภาพ ซึ่งรวมถึง

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

  • สิทธิ์เข้าถึงฟีเจอร์ฮาร์ดแวร์ขั้นสูง - แอปกล้อง OEM มีสิทธิ์เข้าถึงอัลกอริทึมที่ปรับแต่งฮาร์ดแวร์โดยเฉพาะ (โหมดกลางคืน, HDR, การสลับเลนส์ที่เฉพาะเจาะจง) ซึ่งทำซ้ำด้วยตนเองได้ยากหรือเป็นไปไม่ได้

วิธีที่ 2: ใช้ Jetpack CameraX

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

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

เขียน

เมื่อใช้ Jetpack Compose ให้ใช้ไลบรารี androidx.camera:camera-compose โดยเฉพาะ ไลบรารีมี CameraXViewfinder ที่ประกอบได้ ซึ่งออกแบบมาโดยเฉพาะเพื่อจัดการกับรูปทรงที่ซับซ้อนของการปรับขนาด การหมุน และอัตราส่วนภาพภายในวงจร Compose

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

  • การแปลงพิกัดอัตโนมัติ - ส่วนที่ยากที่สุดอย่างหนึ่งในการสร้าง แอปกล้องคือการแมปการแตะของผู้ใช้ (พิกัด x, y บนหน้าจอ) กับ ระบบพิกัดของเซ็นเซอร์กล้อง (0-1, 0-1 หมุน) สำหรับการโฟกัสและการวัดแสง CameraXViewfinder มี CoordinateTransformer ที่จัดการคณิตศาสตร์ โดยอัตโนมัติ แม้ว่าจะมีการปรับขนาดหน้าต่างหรือพับอุปกรณ์ก็ตาม
  • ลักษณะการทำงานของเลย์เอาต์ที่ถูกต้อง - CameraXViewfinder ทำงานได้อย่างถูกต้องด้วยการจัดลำดับ Z ของ Compose ซึ่งแตกต่างจาก SurfaceView หรือ TextureView คุณสามารถวางซ้อนองค์ประกอบ UI (วงแหวนโฟกัส ตัวควบคุม) หรือใช้ตัวแก้ไข (การปัดเศษมุม ภาพเคลื่อนไหว) โดยไม่ต้องแสดงอาร์ติแฟกต์
  • การปรับขนาดและสัดส่วนภาพ: CameraXViewfinder จะจัดการตรรกะการครอบตัดตรงกลางเทียบกับการปรับให้พอดีตรงกลางภายใน เพื่อให้มั่นใจว่าตัวอย่างจะไม่ยืดเมื่อมีการปรับขนาดหน้าต่างแอปเป็นสัดส่วนภาพที่ไม่เป็นมาตรฐาน (เช่น โหมดหน้าจอแยกหรือโหมดการแสดงหน้าต่างบนเดสก์ท็อป)

ยอดดู

ในแอปที่อิงตามมุมมอง ให้ใช้ PreviewView หรือ ViewFinderView หากใช้ SurfaceView หรือ TextureView โดยตรง คุณต้องคำนวณ สัดส่วนภาพและใช้เมทริกซ์การเปลี่ยนรูปที่ถูกต้องด้วยตนเอง

โซลูชันที่ 3: จัดการการวางแนวและการปรับขนาดแบบไดนามิก

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

หยุดใช้การหมุนอุปกรณ์

อย่าใช้ Display#getRotation() หรือการวางแนวเซ็นเซอร์ทางกายภาพเพียงอย่างเดียว เพื่อกำหนดเลย์เอาต์ UI

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

หลีกเลี่ยงการรีสตาร์ทกิจกรรม

ลักษณะการทำงานเริ่มต้นของ Android จะทำลายกิจกรรมของแอปเมื่อมีการเปลี่ยนแปลงการกำหนดค่า (เช่น การปรับขนาดหน้าต่าง) สำหรับแอปกล้อง ปัญหานี้จะปรากฏเป็นการกะพริบของจอแสดงผลหรือ การเชื่อมต่อขาดหายระหว่างวิดีโอคอล

สัดส่วนภาพและการครอบตัด

ปัญหาที่พบบ่อยในอุปกรณ์พับได้และหน้าต่างเดสก์ท็อปคือการยืดตัวอย่าง ซึ่งฟีดกล้อง 4:3 จะถูกบังคับให้แสดงในหน้าต่าง 16:9 หรือ 1:1

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

โบนัส: การรองรับประสบการณ์การใช้งานที่เหมาะกับอุปกรณ์พับได้

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

โหมดตั้งโต๊ะ (การจับภาพแบบแฮนด์ฟรี)

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

รูปที่ 5 แอปการสื่อสารในโหมดวางบนโต๊ะ: ช่องมองภาพของกล้องอยู่ด้านบนของบานพับ และตัวควบคุมอยู่ด้านล่าง

โหมดจอแสดงผลด้านหลัง (เซลฟีคุณภาพสูง)

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

โหมด Dual Screen (แสดงตัวอย่างวิชา)

  • โหมด 2 หน้าจอช่วยให้คุณแสดงตัวอย่างกล้องได้ทั้งหน้าจอด้านในและ ด้านนอกพร้อมกัน ฟีเจอร์นี้เหมาะอย่างยิ่งสำหรับการถ่ายภาพบุคคล โดยตัวแบบจะเห็นตัวเองบนหน้าจอด้านนอกและปรับท่าทางได้ ขณะที่คุณจัดเฟรมภาพบนหน้าจอด้านใน
  • โหมดหน้าจอคู่จะสร้างหน้าต่างการนำเสนอรองบนหน้าจอฝาพับ ซึ่งแตกต่างจากโหมดจอแสดงผลด้านหลัง (ซึ่งจะย้ายแอปทั้งหมด)
รูปที่ 5 แอปกล้องในโหมด Dual Screen