fix: change camera preview to full screen size

This commit is contained in:
Roy Matero 2024-02-26 18:41:21 -08:00
parent 6f8b68c7b2
commit 386614800b
2 changed files with 89 additions and 136 deletions

View File

@ -1,56 +1,56 @@
package app.myzel394.alibi.ui.components.RecorderScreen.atoms package app.myzel394.alibi.ui.components.RecorderScreen.atoms
import android.util.Log
import android.view.ViewGroup import android.view.ViewGroup
import androidx.camera.core.CameraSelector import androidx.camera.core.CameraSelector
import androidx.camera.core.Preview import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView import androidx.camera.view.PreviewView
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
import app.myzel394.alibi.ui.utils.getCameraProvider
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Composable @Composable
fun CameraPreview( fun CameraPreview(
modifier: Modifier = Modifier, modifier: Modifier,
scaleType: PreviewView.ScaleType = PreviewView.ScaleType.FILL_CENTER,
cameraSelector: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA cameraSelector: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
) { ) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val lifecycleOwner = LocalLifecycleOwner.current val lifecycleOwner = LocalLifecycleOwner.current
AndroidView(
modifier = modifier,
factory = { context ->
val previewView = PreviewView(context).apply {
this.scaleType = scaleType
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
// CameraX Preview UseCase Box(modifier = modifier) {
val previewUseCase = Preview.Builder() // Video preview
.build() AndroidView(
.also { factory = { context ->
it.setSurfaceProvider(previewView.surfaceProvider) val previewView = PreviewView(context).apply {
} layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
coroutineScope.launch { ViewGroup.LayoutParams.MATCH_PARENT,
val cameraProvider = ProcessCameraProvider.getInstance(context).get()
try {
// Must unbind the use-cases before rebinding them.
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
lifecycleOwner, cameraSelector, previewUseCase
) )
} catch (ex: Exception) {
} }
} val previewUseCase = Preview.Builder()
.build()
.also { it.setSurfaceProvider(previewView.surfaceProvider) }
previewView coroutineScope.launch {
} val cameraProvider = context.getCameraProvider()
) try {
} cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector,
previewUseCase
)
} catch (ex: Exception) {
Log.e("CameraPreview", "Use case binding failed", ex)
}
}
previewView
},
)
}
}

View File

@ -1,23 +1,17 @@
package app.myzel394.alibi.ui.components.RecorderScreen.organisms package app.myzel394.alibi.ui.components.RecorderScreen.organisms
import android.content.res.Configuration import android.content.res.Configuration
import android.util.Log
import android.view.ViewGroup
import androidx.camera.core.Preview
import androidx.camera.view.PreviewView
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CameraAlt import androidx.compose.material.icons.filled.CameraAlt
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
@ -32,22 +26,19 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import app.myzel394.alibi.R import app.myzel394.alibi.R
import app.myzel394.alibi.ui.components.RecorderScreen.atoms.CameraPreview
import app.myzel394.alibi.ui.components.RecorderScreen.atoms.TorchStatus import app.myzel394.alibi.ui.components.RecorderScreen.atoms.TorchStatus
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingControl import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingControl
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingStatus import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingStatus
import app.myzel394.alibi.ui.models.VideoRecorderModel import app.myzel394.alibi.ui.models.VideoRecorderModel
import app.myzel394.alibi.ui.utils.CameraInfo import app.myzel394.alibi.ui.utils.CameraInfo
import app.myzel394.alibi.ui.utils.KeepScreenOn import app.myzel394.alibi.ui.utils.KeepScreenOn
import app.myzel394.alibi.ui.utils.getCameraProvider
import com.valentinilk.shimmer.shimmer import com.valentinilk.shimmer.shimmer
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -61,78 +52,79 @@ fun VideoRecordingStatus(
when (orientation) { when (orientation) {
Configuration.ORIENTATION_LANDSCAPE -> { Configuration.ORIENTATION_LANDSCAPE -> {
Row( Box {
modifier = Modifier.fillMaxSize(), CameraPreview(
horizontalArrangement = Arrangement.SpaceEvenly, modifier = Modifier,
verticalAlignment = Alignment.CenterVertically, cameraSelector = videoRecorder.cameraSelector
) { )
Column( Row(
horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement horizontalArrangement = Arrangement.SpaceEvenly,
.spacedBy(32.dp), verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.weight(1f)
.fillMaxWidth(0.9f)
.align(Alignment.CenterVertically),
) {
_VideoGeneralInfo(videoRecorder)
_VideoRecordingStatus(videoRecorder)
}
Box(
modifier = Modifier
.weight(1f)
.fillMaxWidth(0.9f)
) { ) {
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement verticalArrangement = Arrangement
.spacedBy(32.dp), .spacedBy(32.dp),
horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier
.weight(1f)
.fillMaxWidth(0.9f)
.align(Alignment.CenterVertically),
) { ) {
_VideoControls(videoRecorder) _VideoGeneralInfo(videoRecorder)
CameraPreview( _VideoRecordingStatus(videoRecorder)
videoRecorder, }
modifier = Modifier Box(
.aspectRatio(5 / 2F) modifier = Modifier
.padding(horizontal = 12.dp) .weight(1f)
) .fillMaxWidth(0.9f)
HorizontalDivider() ) {
_PrimitiveControls(videoRecorder) Column(
verticalArrangement = Arrangement
.spacedBy(32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
_VideoControls(videoRecorder)
HorizontalDivider()
_PrimitiveControls(videoRecorder)
}
} }
} }
} }
} }
else -> { else -> {
Column( Box {
modifier = Modifier
.fillMaxSize()
.padding(bottom = 32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceBetween,
) {
CameraPreview( CameraPreview(
videoRecorder, modifier = Modifier modifier = Modifier,
.padding(24.dp) cameraSelector = videoRecorder.cameraSelector
.aspectRatio(3 / 2F)
) )
Column( Column(
modifier = Modifier
.fillMaxSize()
.padding(bottom = 32.dp),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement verticalArrangement = Arrangement.SpaceBetween,
.spacedBy(16.dp),
) { ) {
_VideoGeneralInfo(videoRecorder) Column(
_VideoRecordingStatus(videoRecorder) horizontalAlignment = Alignment.CenterHorizontally,
} verticalArrangement = Arrangement
.spacedBy(16.dp),
) {
_VideoGeneralInfo(videoRecorder)
_VideoRecordingStatus(videoRecorder)
}
Column( Column(
verticalArrangement = Arrangement verticalArrangement = Arrangement
.spacedBy(16.dp), .spacedBy(16.dp),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
_VideoControls(videoRecorder) _VideoControls(videoRecorder)
HorizontalDivider() HorizontalDivider()
_PrimitiveControls(videoRecorder) _PrimitiveControls(videoRecorder)
}
} }
} }
} }
@ -140,45 +132,6 @@ fun VideoRecordingStatus(
} }
@Composable
fun CameraPreview(videoRecorder: VideoRecorderModel, modifier: Modifier) {
val coroutineScope = rememberCoroutineScope()
val lifecycleOwner = LocalLifecycleOwner.current
Box(modifier = modifier.clip(RoundedCornerShape(12.dp))) {
// Video preview
AndroidView(
factory = { context ->
val previewView = PreviewView(context).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
)
}
val previewUseCase = Preview.Builder()
.build()
.also { it.setSurfaceProvider(previewView.surfaceProvider) }
coroutineScope.launch {
val cameraProvider = context.getCameraProvider()
try {
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
lifecycleOwner,
videoRecorder.cameraSelector,
previewUseCase
)
} catch (ex: Exception) {
Log.e("CameraPreview", "Use case binding failed", ex)
}
}
previewView
},
)
}
}
@Composable @Composable
fun _VideoGeneralInfo(videoRecorder: VideoRecorderModel) { fun _VideoGeneralInfo(videoRecorder: VideoRecorderModel) {
val context = LocalContext.current val context = LocalContext.current