Skip to content

Commit

Permalink
implement tap to focus
Browse files Browse the repository at this point in the history
  • Loading branch information
Kimblebee committed Jul 19, 2023
1 parent 885b37d commit f761acd
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 18 deletions.
3 changes: 3 additions & 0 deletions camera-viewfinder-compose/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ dependencies {
implementation composeBom
androidTestImplementation composeBom

// Compose - Material Design 3
implementation 'androidx.compose.material3:material3'

// Compose - Testing
androidTestImplementation "androidx.compose.ui:ui-test-junit4"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ package com.google.jetpackcamera.viewfinder
import android.graphics.Bitmap
import android.util.Log
import android.view.Surface
import com.google.jetpackcamera.viewfinder.surface.CombinedSurface
import com.google.jetpackcamera.viewfinder.surface.CombinedSurfaceEvent
import com.google.jetpackcamera.viewfinder.surface.SurfaceType
import android.view.View
import androidx.camera.core.Preview.SurfaceProvider
import androidx.camera.core.SurfaceRequest
import androidx.camera.view.PreviewView.ImplementationMode
Expand All @@ -34,6 +32,9 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import com.google.jetpackcamera.viewfinder.surface.CombinedSurface
import com.google.jetpackcamera.viewfinder.surface.CombinedSurfaceEvent
import com.google.jetpackcamera.viewfinder.surface.SurfaceType
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.flow.mapNotNull
Expand All @@ -45,7 +46,8 @@ fun CameraPreview(
modifier: Modifier,
implementationMode: ImplementationMode = ImplementationMode.COMPATIBLE,
onSurfaceProviderReady: (SurfaceProvider) -> Unit = {},
onRequestBitmapReady: (() -> Bitmap?) -> Unit
onRequestBitmapReady: (() -> Bitmap?) -> Unit,
setSurfaceView: (View) -> Unit
) {
Log.d(TAG, "CameraPreview")

Expand All @@ -58,6 +60,7 @@ fun CameraPreview(

PreviewSurface(
surfaceRequest = surfaceRequest,
setView = setSurfaceView
)

}
Expand All @@ -68,6 +71,7 @@ fun PreviewSurface(
// onRequestBitmapReady: (() -> Bitmap?) -> Unit,
type: SurfaceType = SurfaceType.TEXTURE_VIEW,
implementationMode: ImplementationMode = ImplementationMode.COMPATIBLE,
setView: (View) -> Unit
) {
Log.d(TAG, "PreviewSurface")

Expand All @@ -89,6 +93,7 @@ fun PreviewSurface(
when (implementationMode) {
ImplementationMode.PERFORMANCE -> TODO()
ImplementationMode.COMPATIBLE -> CombinedSurface(
setView = setView,
onSurfaceEvent = { event ->
surface = when (event) {
is CombinedSurfaceEvent.SurfaceAvailable -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.google.jetpackcamera.viewfinder.surface
import android.graphics.Bitmap
import android.util.Log
import android.view.Surface
import android.view.View
import androidx.compose.runtime.Composable
import com.google.jetpackcamera.viewfinder.surface.SurfaceType.*

Expand All @@ -29,6 +30,7 @@ fun CombinedSurface(
onSurfaceEvent: (CombinedSurfaceEvent) -> Unit,
onRequestBitmapReady: (() -> Bitmap?) -> Unit = {},
type: SurfaceType = TEXTURE_VIEW,
setView: (View) -> Unit
) {
Log.d(TAG, "PreviewTexture")

Expand All @@ -46,10 +48,12 @@ fun CombinedSurface(
is SurfaceHolderEvent.SurfaceChanged -> {
// TODO(yasith@)
}

}
}

TEXTURE_VIEW -> Texture(

{
when (it) {
is SurfaceTextureEvent.SurfaceTextureAvailable -> {
Expand All @@ -70,7 +74,8 @@ fun CombinedSurface(
}
true
},
onRequestBitmapReady
onRequestBitmapReady,
setView = setView
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import android.graphics.Bitmap
import android.graphics.SurfaceTexture
import android.util.Log
import android.view.TextureView
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.compose.runtime.Composable
Expand All @@ -34,8 +35,9 @@ private const val TAG = "Texture"
@Composable
fun Texture(
onSurfaceTextureEvent: (SurfaceTextureEvent) -> Boolean = { _ -> true },
onRequestBitmapReady: (() -> Bitmap?) -> Unit
) {
onRequestBitmapReady: (() -> Bitmap?) -> Unit,
setView: (View) -> Unit,
) {
Log.d(TAG, "Texture")

var textureView: TextureView? by remember { mutableStateOf(null) }
Expand Down Expand Up @@ -91,9 +93,11 @@ fun Texture(
}
}, update = {
textureView = it
setView(textureView!!)
onRequestBitmapReady { -> it.bitmap }
}
)

}

sealed interface SurfaceTextureEvent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.google.jetpackcamera.domain.camera

import android.view.Display
import androidx.camera.core.Preview
import com.google.jetpackcamera.settings.model.CameraAppSettings
import com.google.jetpackcamera.settings.model.FlashModeStatus
Expand Down Expand Up @@ -52,4 +53,5 @@ interface CameraUseCase {

fun setFlashMode(flashModeStatus: FlashModeStatus)
suspend fun flipCamera(isFrontFacing: Boolean)
fun tapToFocus(display: Display, surfaceWidth: Int, surfaceHeight: Int, x:Float, y:Float)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ import android.content.ContentValues
import android.provider.MediaStore
import android.util.Log
import android.util.Rational
import android.view.Display
import androidx.camera.core.Camera
import androidx.camera.core.CameraSelector
import androidx.camera.core.CameraSelector.LensFacing
import androidx.camera.core.DisplayOrientedMeteringPointFactory
import androidx.camera.core.FocusMeteringAction
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.ImageProxy
Expand Down Expand Up @@ -187,6 +190,32 @@ class CameraXCameraUseCase @Inject constructor(
)
}

override fun tapToFocus(
display: Display,
surfaceWidth: Int,
surfaceHeight: Int,
x: Float,
y: Float
) {
if (camera != null){
val meteringPoint = DisplayOrientedMeteringPointFactory(
display,
camera!!.cameraInfo,
surfaceWidth.toFloat(),
surfaceHeight.toFloat()
)
.createPoint(x, y);

val action = FocusMeteringAction.Builder(meteringPoint).build()

camera!!.cameraControl.startFocusAndMetering(action)
Log.d(TAG, "Tap to focus on: $meteringPoint")

}


}

override fun setFlashMode(flashModeStatus: FlashModeStatus) {
imageCaptureUseCase.flashMode = when (flashModeStatus) {
FlashModeStatus.OFF -> ImageCapture.FLASH_MODE_OFF // 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.google.jetpackcamera.domain.camera.test

import android.view.Display
import androidx.camera.core.CameraSelector
import androidx.camera.core.Preview
import com.google.jetpackcamera.domain.camera.CameraUseCase
Expand Down Expand Up @@ -88,4 +89,14 @@ class FakeCameraUseCase : CameraUseCase {
override suspend fun flipCamera(isFrontFacing: Boolean) {
isLensFacingFront = isFrontFacing
}

override fun tapToFocus(
display: Display,
surfaceWidth: Int,
surfaceHeight: Int,
x: Float,
y: Float
) {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.google.jetpackcamera.feature.preview

import android.util.Log
import android.view.View
import androidx.camera.core.Preview.SurfaceProvider
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.border
Expand All @@ -31,7 +32,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
Expand All @@ -42,6 +42,7 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
Expand All @@ -61,6 +62,7 @@ private const val TAG = "PreviewScreen"
/**
* Screen used for the Preview feature.
*/
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun PreviewScreen(
onNavigateToSettings: () -> Unit,
Expand All @@ -77,6 +79,7 @@ fun PreviewScreen(
Log.d(TAG, "onSurfaceProviderReady")
deferredSurfaceProvider.complete(it)
}
lateinit var viewInfo: View
val transformableState = rememberTransformableState(onTransformation = { zoomChange, _, _ ->
viewModel.setZoomScale(zoomChange)
})
Expand All @@ -97,23 +100,44 @@ fun PreviewScreen(
Text(text = stringResource(R.string.camera_not_ready))
} else if (previewUiState.cameraState == CameraState.READY) {
Box(
modifier = Modifier.fillMaxSize().transformable(state = transformableState)
modifier = Modifier
.fillMaxSize()
.transformable(state = transformableState)
.pointerInput(Unit) {
detectTapGestures(
onDoubleTap = { offset ->
Log.d(TAG, "onDoubleTap $offset")
viewModel.flipCamera()
},
onTap = { offset ->
try {
viewModel.tapToFocus(
viewInfo.display,
viewInfo.width,
viewInfo.height,
offset.x, offset.y
)
Log.d(TAG, "onTap $offset")
} catch(e : UninitializedPropertyAccessException) {
Log.d(TAG, "onTap $offset")
e.printStackTrace()
}
}
)
},
) {
CameraPreview(
modifier = Modifier
.fillMaxSize()
.pointerInput(Unit) {
detectTapGestures(
onDoubleTap = { offset ->
Log.d(TAG, "onDoubleTap $offset")
viewModel.flipCamera()
}
)
},
,
onSurfaceProviderReady = onSurfaceProviderReady,
onRequestBitmapReady = {
val bitmap = it.invoke()
}
},
setSurfaceView = { s: View ->
println("haudy, gettin da surfaceview")
viewInfo = s
println(viewInfo)}
)

QuickSettingsScreen(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.google.jetpackcamera.feature.preview

import android.util.Log
import android.view.Display
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview.SurfaceProvider
import androidx.lifecycle.ViewModel
Expand Down Expand Up @@ -197,4 +198,14 @@ class PreviewViewModel @Inject constructor(
)
}
}

fun tapToFocus(display: Display, surfaceWidth: Int, surfaceHeight: Int, x: Float, y: Float) {
cameraUseCase.tapToFocus(
display = display,
surfaceWidth = surfaceWidth,
surfaceHeight = surfaceHeight,
x = x,
y = y
)
}
}

0 comments on commit f761acd

Please sign in to comment.