Отображение предварительного просмотра с камеры
Подключите предварительный просмотр в реальном времени
«Отображение предварительного просмотра с камеры» — бесплатный урок Android Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 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.
Оба объекта нужны для настройки поставщика камеры и привязки сценариев использования.
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.currentСоздание сценария использования Preview
Сценарий использования Preview передаёт кадры на поверхность. Создав его, подключите его к PreviewView, вызвав setSurfaceProvider и передав поставщик поверхности представления.
Именно эта связь позволяет изображению с камеры появиться на экране.
val preview = Preview.Builder().build()
preview.setSurfaceProvider(previewView.surfaceProvider)Привязка внутри сопрограммы
Поставщик получается асинхронно, поэтому выполняйте эту операцию в сопрограмме. Используйте LaunchedEffect, привязанный к представлению, чтобы код выполнился один раз. Внутри получите поставщик с помощью await, отмените предыдущие привязки, а затем привяжите предварительный просмотр.
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.Собираем всё вместе
Ниже приведён полный компонуемый элемент предварительного просмотра. Обратите внимание на последовательность: создайте 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в сопрограмме с помощью await. - Создайте
Preview, вызовитеsetSurfaceProvider,unbindAll(), а затемbindToLifecycle.
Далее вы добавите сценарий использования ImageCapture и сделаете настоящую фотографию.
Изучай Kotlin с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 36
- Уроки
- 152
Часто задаваемые вопросы
Урок «Отображение предварительного просмотра с камеры» бесплатный?
Да — полный текст урока «Отображение предварительного просмотра с камеры» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 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 включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Обзор CameraX
- Отображение предварительного просмотра с камеры
- Съёмка фотографий
- Запись видео