0Pricing
Android Academy · درس

عرض معاينة الكاميرا

وصّل معاينة مباشرة

عرض معاينة الكاميرا درس مجاني في Android Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Android Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Android Academy 4 دروس في المجموع.

الهدف: معاينة مباشرة

أول ما تحتاج إليه معظم تطبيقات الكاميرا هو معاينة مباشرة — عرض في الوقت الفعلي لما تراه الكاميرا. في هذا الدرس ستنشئ شاشة Compose تعرض بث الكاميرا بملء الشاشة.

ستجمع ثلاثة مكونات: PreviewView وحالة الاستخدام Preview وProcessCameraProvider المرتبط.

طلب إذن الكاميرا

قبل عرض المعاينة، تحتاج إلى إذن المستخدم. في Compose، يجعل Accompanist (أو واجهة الأذونات الرسمية) ذلك سهلًا باستخدام 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 هو View تقليدي في Android، لذلك تستضيفه داخل Compose باستخدام AndroidView. تنشئ lambda‏ 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.

يلزم كلاهما لإعداد موفّر الكاميرا وربط حالات الاستخدام.

val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current

إنشاء حالة استخدام المعاينة

تبث حالة الاستخدام Preview الإطارات إلى سطح. وبعد إنشائها، تصلها بـ PreviewView باستخدام setSurfaceProvider مع موفّر سطح العرض.

هذه هي الوصلة التي تجعل صورة الكاميرا تظهر فعليًا على الشاشة.

val preview = Preview.Builder().build()
preview.setSurfaceProvider(previewView.surfaceProvider)

الربط داخل Coroutine

يتم الحصول على الموفّر بشكل غير متزامن، لذا نفّذ ذلك داخل coroutine. استخدم LaunchedEffect المرتبط بالعرض حتى يعمل مرة واحدة. وداخله، انتظر الموفّر، وألغِ ربط أي شيء سابق، ثم اربط المعاينة.

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 التنفيذ حتى يكتمل، محولًا تعليمات callback إلى تعليمات متسلسلة واضحة.

أضف التبعية 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 داخل coroutine.
  • أنشئ Preview، واستدعِ setSurfaceProvider وunbindAll()، ثم bindToLifecycle.

بعد ذلك، ستضيف حالة الاستخدام ImageCapture وتلتقط صورة حقيقية.

الأسئلة الشائعة

هل درس «عرض معاينة الكاميرا» مجاني؟

نعم — نص درس «عرض معاينة الكاميرا» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Android Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Android Academy 4 دروس في المجموع.

ماذا ستتعلم في «عرض معاينة الكاميرا»؟

وصّل معاينة مباشرة تتمرن على Android Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Android Academy؟

لا تُشترط خبرة سابقة. Android Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «عرض معاينة الكاميرا»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Android Academy هذا؟

نعم. كل درس في Android Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. نظرة عامة على CameraX
  2. عرض معاينة الكاميرا
  3. التقاط الصور
  4. تسجيل الفيديو
← العودة إلى Android Academy