Индикатор автофокуса отображается в неправильном положенииAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Индикатор автофокуса отображается в неправильном положении

Сообщение Anonymous »

На экране моей камеры Composable у меня есть CameraxViewFinder Composable для отображения предварительного просмотра камеры пользователю. Всякий раз, когда пользователь нажимает на этот предварительный просмотр, должен отображаться индикатор фокусировки. Но индикатор отображается в неправильном месте. < /P>
После отладки я узнал, что проблема заключается в
ontap функции модификатора, где он дает неправильный смещение по какой -то причине?
. вещи?

Код: Выделить всё

@Composable
fun CameraScreen(
modifier: Modifier = Modifier,
permissionStatus: Boolean?,
state: CameraState,
onEvent: (CameraEvent) -> Unit = {},
viewModel: CameraViewModel = hiltViewModel(),
onNavigateToImageEdit : (AppScreen.MediaEdit) -> Unit
) {
val context = LocalContext.current
val app = context.applicationContext
val lifecycleOwner = LocalLifecycleOwner.current
var showImagePreview by remember { mutableStateOf(false) }
val imageUri by viewModel.capturedImageUri.collectAsStateWithLifecycle()

var co by remember { mutableStateOf(Offset(0f,0f)) }

//    val ratio = if(state.aspectRatio == AspectRatio.RATIO_16_9)

val mediaLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.PickVisualMedia()
) { uri ->

if (uri!=null){
Log.d("CameraScreen", "Camera Screen content uri : ${uri.toString()} ")
onNavigateToImageEdit(AppScreen.MediaEdit(uri.toString()))
}

}

LaunchedEffect(Unit) {
viewModel.errorFlow.collect { message ->
Log.e(TAG, "CameraScreen: error while capturing $message")
}

}
val coordinateTransformer = remember { MutableCoordinateTransformer() }

var autofocusRequest by remember { mutableStateOf(UUID.randomUUID() to Offset.Unspecified) }

val autofocusRequestId = autofocusRequest.first
// Show the autofocus indicator if the offset is specified
var showAutofocusIndicator = autofocusRequest.second.isSpecified
// Cache the initial coords for each autofocus request
val autofocusCoords = remember(autofocusRequestId) { autofocusRequest.second }

// Queue hiding the request for each unique autofocus tap
if (showAutofocusIndicator) {
LaunchedEffect(autofocusRequestId) {
delay(2000)
autofocusRequest = autofocusRequestId to Offset.Unspecified

//            if (!isUserInteractingWithSlider) {
//
}
}

Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Black)
,
) {
Log.d(TAG, "CameraScreen: permissionStatus = ${permissionStatus} ")
if (permissionStatus != null && !permissionStatus) {
Text(
text = "Camera permission has not been granted",
modifier = Modifier.align(Alignment.Center)
)
}
if (permissionStatus != null &&  permissionStatus) {
Text(
text = "Camera",
modifier = Modifier.align(Alignment.Center)
)
}

state.surfaceRequest?.let { surfaceRequest ->
CameraXViewfinder(
surfaceRequest = surfaceRequest,
coordinateTransformer = coordinateTransformer,
modifier = Modifier
.align(Alignment.Center)
.fillMaxWidth()
.aspectRatio(state.aspectRatio.ratio)
.pointerInput(Unit) {
detectTapGestures(
onDoubleTap = { tapCoords ->
onEvent(CameraEvent.ChangeLensFacing)
},
onTap = {offset ->
co = offset
with(coordinateTransformer){
onEvent(CameraEvent.TapToFocus(offset.transform()))
}

autofocusRequest = UUID.randomUUID() to offset
}
)
}
.pointerInput(Unit) {
//                        detectTransformGestures { _, _, zoom, _ ->
//                            val scale = (state.zoomScale + (zoom - 1f)).coerceIn(0f, 1f)
//                            Log.d(TAG, "zoom scale :  $scale")
//                            onEvent(CameraEvent.Zoom(scale))
//                        }
}
)

AnimatedVisibility(
visible = showAutofocusIndicator,
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier
) {
Spacer(
Modifier
.offset { autofocusCoords.takeOrElse { Offset.Zero }.round() }
.offset((-24).dp, (-24).dp)
.border(1.dp, Color.White, CircleShape)
.size(48.dp)

)
}

}

UpperBox(
modifier = Modifier.align(Alignment.TopEnd),
torchState = state.torchState,
onTorchToggle = {
onEvent(CameraEvent.TorchToggle)
},
onAspectRatioChange = {
onEvent(CameraEvent.ToggleAspectRatio)
}
)

LowerBox(
modifier = Modifier
.align(Alignment.BottomCenter),
onToggleCamera = {
onEvent(CameraEvent.ChangeLensFacing)
},
onChooseFromGallery = {
mediaLauncher.launch(
PickVisualMediaRequest(
ActivityResultContracts.PickVisualMedia.ImageOnly
)
)
},
onClick = {
val file = createTempFile(
context
)
onEvent(CameraEvent.TakePicture(file))
}
)

// tap indicator for debugging
Surface(
modifier = Modifier
.offset{co.round()}
.height(10.dp).width(10.dp)
.background(Color.White)

) {

}

}

LaunchedEffect(imageUri) {
if(imageUri!=null){
onNavigateToImageEdit(AppScreen.MediaEdit(imageUri.toString()))
onEvent(CameraEvent.Reset)
}
}

LaunchedEffect(lifecycleOwner, state.lensFacing,state.aspectRatio) {
lifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
onEvent(CameraEvent.Preview(app, lifecycleOwner))
}

}

}
cameraxviewfinder

Код: Выделить всё

        state.surfaceRequest?.let { surfaceRequest ->
CameraXViewfinder(
surfaceRequest = surfaceRequest,
coordinateTransformer = coordinateTransformer,
modifier = Modifier
.align(Alignment.Center)
.fillMaxWidth()
.aspectRatio(state.aspectRatio.ratio)
.pointerInput(Unit) {
detectTapGestures(
onDoubleTap = { tapCoords ->
onEvent(CameraEvent.ChangeLensFacing)
},
onTap = {offset ->
co = offset
with(coordinateTransformer){
onEvent(CameraEvent.TapToFocus(offset.transform()))
}

autofocusRequest = UUID.randomUUID() to offset
}
)
}
.pointerInput(Unit) {
//                        detectTransformGestures { _, _, zoom, _ ->
//                            val scale = (state.zoomScale + (zoom - 1f)).coerceIn(0f, 1f)
//                            Log.d(TAG, "zoom scale :  $scale")
//                            onEvent(CameraEvent.Zoom(scale))
//                        }
}
)
cameramanager

Код: Выделить всё

package com.example.memories.feature.feature_camera.data.data_source

import android.content.Context
import android.util.Log
import androidx.camera.core.CameraControl
import androidx.camera.core.CameraInfo
import androidx.camera.core.CameraSelector
import androidx.camera.core.CameraSelector.LENS_FACING_BACK
import androidx.camera.core.CameraSelector.LENS_FACING_FRONT
import androidx.camera.core.FocusMeteringAction
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.MeteringPoint
import androidx.camera.core.Preview
import androidx.camera.core.SurfaceOrientedMeteringPointFactory
import androidx.camera.core.SurfaceRequest
import androidx.camera.core.UseCaseGroup
import androidx.camera.core.resolutionselector.AspectRatioStrategy
import androidx.camera.core.resolutionselector.ResolutionSelector
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.lifecycle.awaitInstance
import androidx.compose.ui.geometry.Offset
import androidx.lifecycle.LifecycleOwner
import com.example.memories.feature.feature_camera.domain.model.AspectRatio
import com.example.memories.feature.feature_camera.domain.model.CaptureResult
import com.example.memories.feature.feature_camera.domain.model.LensFacing
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.suspendCancellableCoroutine
import java.io.File
import java.util.concurrent.Executor
import java.util.concurrent.Executors
import kotlin.coroutines.resume

class CameraManager {
companion object {
private const val TAG = "CameraManager"
}

private var surfaceRequestCallback: ((SurfaceRequest) ->  Unit)? = null
private var cameraControl: CameraControl? = null
private var cameraInfo: CameraInfo? = null

private lateinit var cameraPreviewUseCase: Preview
private lateinit var imageCaptureUseCase: ImageCapture
private lateinit var processCameraProvider: ProcessCameraProvider
private lateinit var surfaceMeteringPointFactory: SurfaceOrientedMeteringPointFactory
private val resolutionSelectorBuilder = ResolutionSelector.Builder()

//    private val cameraPreviewUseCase = Preview.Builder().build().apply {
//        setSurfaceProvider { surfaceRequest ->
//            surfaceRequestCallback?.invoke(surfaceRequest)
//        }
//
//    }
//
//    private val  imageCaptureUseCase  = ImageCapture.Builder()
//        .setTargetRotation(cameraPreviewUseCase!!.targetRotation)
//        .build()

init {
setAspectRatio(AspectRatio.RATIO_4_3)

//        initUseCases()

}

fun initUseCases() {
cameraPreviewUseCase = Preview.Builder()
.setResolutionSelector(resolutionSelectorBuilder.build())
.build()

cameraPreviewUseCase!!.setSurfaceProvider { surfaceRequest ->
surfaceRequestCallback?.invoke(surfaceRequest)
surfaceMeteringPointFactory = SurfaceOrientedMeteringPointFactory(
surfaceRequest.resolution.width.toFloat(),
surfaceRequest.resolution.height.toFloat())
}

imageCaptureUseCase = ImageCapture.Builder()
.setTargetRotation(cameraPreviewUseCase!!.targetRotation)
.setResolutionSelector(resolutionSelectorBuilder.build())
.build()
}

suspend fun bindToCamera(
appContext: Context,
lifecycleOwner: LifecycleOwner,
lensFacing: LensFacing = LensFacing.BACK,
torch: Boolean = false
) {
processCameraProvider = ProcessCameraProvider.awaitInstance(appContext)
unbind(processCameraProvider)

val cameraSelector = CameraSelector.Builder()
.requireLensFacing(if (lensFacing == LensFacing.BACK) LENS_FACING_BACK else LENS_FACING_FRONT)
.build()
val camera = processCameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector,
UseCaseGroup.Builder()
.addUseCase(cameraPreviewUseCase)
.addUseCase(imageCaptureUseCase)
.build()
)

cameraControl = camera.cameraControl
cameraInfo = camera.cameraInfo

cameraControl?.enableTorch(torch)

Log.d(TAG, "Torch Value : ${torch}")

// Cancellation signals we're done with the camera
try {
awaitCancellation()
} finally {
unbind(processCameraProvider)
}
}

fun unbind(processCameraProvider: ProcessCameraProvider) {
processCameraProvider.unbindAll()
}

fun setSurfaceRequestCallback(callback: (SurfaceRequest) ->  Unit) {
surfaceRequestCallback = callback
}

fun tapToFocus(tapCoords: Offset) {
Log.d(TAG, "tapToFocus: offset = ${tapCoords}")
val point: MeteringPoint? =
surfaceMeteringPointFactory?.createPoint(tapCoords.x, tapCoords.y)

if (point != null) {
val meteringAction = FocusMeteringAction.Builder(point).build()
cameraControl?.startFocusAndMetering(meteringAction)
}

Log.d(TAG, "tapToFocus: called")

}

fun setAspectRatio(aspectRatio: AspectRatio = AspectRatio.RATIO_4_3) {
val aspect =
if (aspectRatio == AspectRatio.RATIO_4_3) AspectRatioStrategy.RATIO_4_3_FALLBACK_AUTO_STRATEGY
else AspectRatioStrategy.RATIO_16_9_FALLBACK_AUTO_STRATEGY

setAspect(aspect)

initUseCases()

Log.d(
"CameraManager",
"Aspect Ratio : ${resolutionSelectorBuilder.build().aspectRatioStrategy}"
)
}

private fun setAspect(aspect: AspectRatioStrategy) {
resolutionSelectorBuilder.setAspectRatioStrategy(aspect)
}

@Throws(NullPointerException::class)
fun torchToggle(torch: Boolean) {
if (cameraControl == null) throw NullPointerException("Camera Control Null")

cameraControl?.enableTorch(torch)
}

fun zoom(scale: Float) {
cameraControl?.setLinearZoom(scale)
}

suspend fun takePicture(
file: File
): CaptureResult {
if (imageCaptureUseCase == null) {
val error = IllegalStateException("ImageCapture use case not initialized")
Log.e(TAG, "${error.message}")
return CaptureResult.Error(error)
}

return suspendCancellableCoroutine { continuation ->
val outputFileOptions = ImageCapture.OutputFileOptions.Builder(file).build()
val imageSavedCallback = object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
Log.d(TAG, "${outputFileResults.savedUri}")
if (outputFileResults.savedUri == null) {
Log.e(TAG, "onImageSaved: savedUri is null")
}
continuation.resume(CaptureResult.Success(outputFileResults.savedUri))
}

override fun onError(exception: ImageCaptureException) {
Log.e(TAG, "${exception.message}")
continuation.resume(CaptureResult.Error(exception))
}
}

continuation.invokeOnCancellation {
Log.d(TAG, "Coroutine Cancelled")
}
val executor: Executor = Executors.newSingleThreadExecutor()

imageCaptureUseCase.takePicture(outputFileOptions, executor, imageSavedCallback)

}
}

}

Ваша помощь будет оценена

Подробнее здесь: https://stackoverflow.com/questions/796 ... t-position
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»