การแสดงตัวอย่างจากกล้อง
เชื่อมต่อภาพตัวอย่างแบบสด
การแสดงตัวอย่างจากกล้อง เป็นบทเรียน Android Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Android Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน
เป้าหมาย: ภาพตัวอย่างแบบสด
สิ่งแรกที่แอปกล้องเกือบทุกแอปต้องมีคือ ภาพตัวอย่างแบบสด — มุมมองแบบเรียลไทม์ของสิ่งที่กล้องมองเห็น ในบทเรียนนี้คุณจะสร้างหน้าจอ Compose ที่แสดงภาพจากกล้องเต็มหน้าจอ
คุณจะผสานสามส่วนเข้าด้วยกัน ได้แก่ PreviewView กรณีการใช้งาน Preview และ ProcessCameraProvider ที่เชื่อมไว้
การขอสิทธิ์ใช้กล้อง
ก่อนจะแสดงภาพตัวอย่างได้ คุณต้องได้รับสิทธิ์จากผู้ใช้ก่อน ใน Compose Accompanist (หรือ API สิทธิ์อย่างเป็นทางการ) ช่วยให้ทำได้ง่ายด้วย rememberPermissionState
เริ่มกล้องหลังจากสิทธิ์เป็น granted แล้วเท่านั้น
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun CameraScreen() {
val permission = rememberPermissionState(Manifest.permission.CAMERA)
LaunchedEffect(Unit) { permission.launchPermissionRequest() }
if (permission.status.isGranted) {
CameraPreview()
} else {
Text("Camera permission is required.")
}
}การฝัง PreviewView ใน Compose
PreviewView เป็น Android View แบบดั้งเดิม ดังนั้นคุณจึงโฮสต์ไว้ภายใน Compose ด้วย AndroidView แลมบ์ดา factory จะสร้างมุมมองขึ้นครั้งเดียวและมอบการอ้างอิงให้คุณนำไปกำหนดค่า
เก็บมุมมองที่สร้างขึ้นไว้ เพื่อให้คุณเชื่อมพื้นที่แสดงผลของกล้องเข้ากับมุมมองนั้นได้
@Composable
fun CameraPreview(modifier: Modifier = Modifier) {
AndroidView(
modifier = modifier.fillMaxSize(),
factory = { context ->
PreviewView(context).apply {
scaleType = PreviewView.ScaleType.FILL_CENTER
}
}
)
}การรับ LifecycleOwner
หากต้องการเชื่อมกล้อง คุณต้องมี LifecycleOwner ใน Compose คุณอ่านค่าปัจจุบันด้วย LocalLifecycleOwner.current และอ่านบริบทด้วย LocalContext.current
ต้องใช้ทั้งสองรายการเพื่อเตรียม provider ของกล้องและเชื่อมกรณีการใช้งาน
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.currentการสร้างกรณีการใช้งาน Preview
กรณีการใช้งาน Preview จะส่งเฟรมไปยังพื้นที่แสดงผล หลังจากสร้างแล้ว ให้เชื่อมเข้ากับ PreviewView โดยเรียก setSurfaceProvider พร้อม provider ของพื้นที่แสดงผลจากมุมมอง
การเชื่อมนี้ทำให้ภาพจากกล้องปรากฏบนหน้าจอจริง
val preview = Preview.Builder().build()
preview.setSurfaceProvider(previewView.surfaceProvider)การเชื่อมภายในคอร์รูทีน
การรับ provider เป็นการทำงานแบบอะซิงโครนัส จึงควรทำในคอร์รูทีน ใช้ LaunchedEffect ที่ผูกกับมุมมอง เพื่อให้ทำงานครั้งเดียว ภายในนั้นให้รอ provider ยกเลิกการเชื่อมสิ่งก่อนหน้า แล้วจึงเชื่อมภาพตัวอย่าง
LaunchedEffect(previewView) {
val cameraProvider = ProcessCameraProvider.getInstance(context).await()
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
preview
)
}ส่วนขยาย await()
ProcessCameraProvider.getInstance() คืนค่าเป็น ListenableFuture ส่วนขยาย await() จาก kotlinx-coroutines-guava จะระงับการทำงานจนกว่าค่าจะพร้อม ทำให้โค้ดแบบเรียกกลับกลายเป็นโค้ดลำดับขั้นที่อ่านง่าย
เพิ่มส่วนพึ่งพา org.jetbrains.kotlinx:kotlinx-coroutines-guava เพื่อใช้งานส่วนขยายนี้
import kotlinx.coroutines.guava.await
// Without await you'd use a listener:
// future.addListener({ val provider = future.get() }, executor)
// await() makes it a single suspend call instead.การประกอบทุกอย่างเข้าด้วยกัน
นี่คือ composable สำหรับภาพตัวอย่างฉบับสมบูรณ์ สังเกตลำดับการทำงาน: สร้าง PreviewView ใน factory เก็บการอ้างอิงไว้ แล้วจึงเชื่อมภายใน LaunchedEffect
@Composable
fun CameraPreview(modifier: Modifier = Modifier) {
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val previewView = remember { PreviewView(context) }
LaunchedEffect(previewView) {
val provider = ProcessCameraProvider.getInstance(context).await()
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
provider.unbindAll()
provider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
preview
)
}
AndroidView(
factory = { previewView },
modifier = modifier.fillMaxSize()
)
}ประเภทการปรับขนาด
อัตราส่วนภาพของเซนเซอร์กล้องแทบไม่ตรงกับหน้าจอของคุณ PreviewView.ScaleType ควบคุมวิธีที่ภาพจากกล้องจะพอดีกับมุมมอง:
FILL_CENTER— เติมเต็มมุมมองโดยตัดขอบออก (ใช้บ่อยที่สุด)FIT_CENTER— แสดงทั้งเฟรมพร้อมแถบดำ
เลือก FILL_CENTER สำหรับกล้องเต็มหน้าจอที่ให้ความรู้สึกเต็มอิ่ม
previewView.scaleType = PreviewView.ScaleType.FILL_CENTER
// or
previewView.scaleType = PreviewView.ScaleType.FIT_CENTERการสลับกล้อง
หากต้องการสลับระหว่างกล้องหน้าและกล้องหลัง ให้เก็บตัวเลือกไว้ในสถานะและเชื่อมใหม่เมื่อค่าดังกล่าวเปลี่ยน เนื่องจาก LaunchedEffect จะทำงานซ้ำเมื่อคีย์เปลี่ยน คุณเพียงใส่ตัวเลือกเป็นคีย์
var selector by remember { mutableStateOf(CameraSelector.DEFAULT_BACK_CAMERA) }
LaunchedEffect(selector) {
val provider = ProcessCameraProvider.getInstance(context).await()
provider.unbindAll()
provider.bindToLifecycle(lifecycleOwner, selector, preview)
}
// Flip button toggles 'selector' between front and back.ข้อผิดพลาดที่พบบ่อย
ข้อผิดพลาดสองอย่างทำให้ภาพตัวอย่างเป็นสีดำ:
- ลืมเรียก
setSurfaceProvider— เฟรมไม่มีปลายทางให้ส่งไป - ไม่เรียก
unbindAll()ก่อนเชื่อมใหม่ — CameraX จะแจ้งข้อผิดพลาดหากกรณีการใช้งานถูกเชื่อมไว้สองครั้ง
โปรดจำไว้ด้วยว่า ภาพตัวอย่างจะไม่เริ่มจนกว่าจะได้รับสิทธิ์จริง
ตรวจสอบอย่างรวดเร็ว
ตรวจสอบความเข้าใจเกี่ยวกับการเชื่อมต่อภาพตัวอย่าง
สรุปทบทวน
คุณสร้างภาพตัวอย่างจากกล้องแบบสดใน Compose แล้ว:
- ขอสิทธิ์
CAMERAก่อนเริ่มทำงาน - โฮสต์
PreviewViewด้วยAndroidView - รอ
ProcessCameraProviderภายในคอร์รูทีน - สร้าง
PreviewเรียกsetSurfaceProviderเรียกunbindAll()แล้วจึงเรียกbindToLifecycle
ถัดไป คุณจะเพิ่มกรณีการใช้งาน ImageCapture และถ่ายภาพจริง
คำถามที่พบบ่อย
บทเรียน “การแสดงตัวอย่างจากกล้อง” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การแสดงตัวอย่างจากกล้อง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Android Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การแสดงตัวอย่างจากกล้อง”
เชื่อมต่อภาพตัวอย่างแบบสด คุณปฏิบัติ Android Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Android Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Android Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “การแสดงตัวอย่างจากกล้อง” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Android Academy นี้ได้ไหม
ได้ บทเรียน Android Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ภาพรวม CameraX
- การแสดงตัวอย่างจากกล้อง
- การถ่ายภาพ
- การบันทึกวิดีโอ