最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

android - onTouchListener() not triggering - Stack Overflow

programmeradmin4浏览0评论

I'm trying to set a touch listener to my CameraX preview - ultimately to set the focus but I can't get the touch listener to trigger. My preview is created in a composable and I'm not sure if I am referencing it correctly when I setOnTouchListener(). Should I be using PreviewView - if not how do I get the reference to the preview?

private val handleTouch = OnTouchListener { v, event ->
    val x = event.x.toInt()
    val y = event.y.toInt()

    when (event.action) {
        MotionEvent.ACTION_DOWN -> Log.i("Touch", "touched down")
        MotionEvent.ACTION_MOVE -> Log.i("Touch", "moving: ($x, $y)")
        MotionEvent.ACTION_UP -> Log.i("Touch", "touched up")
    }
    true
}

PreviewView.setOnTouchListener(handleTouch)



}@Composable
fun CameraPreview(
    controller: LifecycleCameraController,
    modifier: Modifier = Modifier
) {
    val lifecycleOwner = LocalLifecycleOwner.current

    // select the highest resolution available
    val screenSize = Size(9, 12)
    val resolutionSelector = ResolutionSelector.Builder()
    .setResolutionStrategy(ResolutionStrategy(screenSize, FALLBACK_RULE_CLOSEST_LOWER_THEN_HIGHER))
    .setAspectRatioStrategy(RATIO_4_3_FALLBACK_AUTO_STRATEGY)
    .build()

    AndroidView(
        factory = {
            PreviewView(it).apply {
                this.controller = controller
                controller.bindToLifecycle(lifecycleOwner)
                //controller.cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
                controller.previewResolutionSelector = resolutionSelector
            }
        },
        modifier = modifier
    )
}

I'm trying to set a touch listener to my CameraX preview - ultimately to set the focus but I can't get the touch listener to trigger. My preview is created in a composable and I'm not sure if I am referencing it correctly when I setOnTouchListener(). Should I be using PreviewView - if not how do I get the reference to the preview?

private val handleTouch = OnTouchListener { v, event ->
    val x = event.x.toInt()
    val y = event.y.toInt()

    when (event.action) {
        MotionEvent.ACTION_DOWN -> Log.i("Touch", "touched down")
        MotionEvent.ACTION_MOVE -> Log.i("Touch", "moving: ($x, $y)")
        MotionEvent.ACTION_UP -> Log.i("Touch", "touched up")
    }
    true
}

PreviewView.setOnTouchListener(handleTouch)



}@Composable
fun CameraPreview(
    controller: LifecycleCameraController,
    modifier: Modifier = Modifier
) {
    val lifecycleOwner = LocalLifecycleOwner.current

    // select the highest resolution available
    val screenSize = Size(9, 12)
    val resolutionSelector = ResolutionSelector.Builder()
    .setResolutionStrategy(ResolutionStrategy(screenSize, FALLBACK_RULE_CLOSEST_LOWER_THEN_HIGHER))
    .setAspectRatioStrategy(RATIO_4_3_FALLBACK_AUTO_STRATEGY)
    .build()

    AndroidView(
        factory = {
            PreviewView(it).apply {
                this.controller = controller
                controller.bindToLifecycle(lifecycleOwner)
                //controller.cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
                controller.previewResolutionSelector = resolutionSelector
            }
        },
        modifier = modifier
    )
}
Share Improve this question edited Mar 21 at 15:28 garrettlynchirl asked Mar 20 at 18:31 garrettlynchirlgarrettlynchirl 91911 silver badges26 bronze badges 4
  • Based on what I see, You are creating multiple instances of PreviewView. Create a global previewView variable and set it to null. Then define it in CameraPreview and attach the handleTouch – Shadman Adman Commented Mar 21 at 11:36
  • Sorry a line of my code copied and pasted twice. "Create a global previewView variable and set it to null." - This I think I know how to do. "define it in CameraPreview and attach the handleTouch" - how do I do this? – garrettlynchirl Commented Mar 21 at 15:30
  • 1 I mean this: previewView = PreviewView(it) .... After the AndroidView part set the touch: PreviewView.setOnTouchListener(handleTouch) I will create an answer if it's still unclear – Shadman Adman Commented Mar 21 at 19:09
  • @Shadman Adman - I posted an answer of what I understood in your comment but still no luck. Can you point out what's wrong? – garrettlynchirl Commented Mar 22 at 17:14
Add a comment  | 

2 Answers 2

Reset to default 0

You also need a Preview builder that I did not see in your code:

Here is the correct version:

private val handleTouch = OnTouchListener { v, event ->
    val x = event.x.toInt()
    val y = event.y.toInt()

    when (event.action) {
        MotionEvent.ACTION_DOWN -> Log.i("Touch", "touched down")
        MotionEvent.ACTION_MOVE -> Log.i("Touch", "moving: ($x, $y)")
        MotionEvent.ACTION_UP -> {
            Log.i("Touch", "touched up")
            v.performClick() // Call performClick when ACTION_UP
        }
    }
    true
}


// Camera preview
@OptIn(ExperimentalCamera2Interop::class)
@Composable
fun CameraPreview() {

    val lensFacing = CameraSelector.LENS_FACING_BACK
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current
    
    //Notice this two variables
    val preview = androidx.camera.core.Preview.Builder().build()
    val previewView = remember {
        PreviewView(context)
    }

    val cameraSelector = CameraSelector.Builder()
        .requireLensFacing(lensFacing)
        .build()

    val cameraProviderFuture = remember {
        ProcessCameraProvider.getInstance(context)
    }


    LaunchedEffect(key1 = Unit) {
        cameraProviderFuture.addListener({
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

            val camera = cameraProvider.bindToLifecycle(
                lifecycleOwner,
                cameraSelector,
                preview
            )

            preview.setSurfaceProvider(previewView.surfaceProvider) // You need to set the provider
            previewView.setOnTouchListener(handleTouch) // Here you can set the onTouch
        
    }, ContextCompat.getMainExecutor(context))
    }

    // Preview
    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(
                Color.Black
            )
    ) {
        AndroidView(
            factory = {
                previewView
            },
            modifier = Modifier.fillMaxSize()
        )
    }
}

If you need to access the PreviewView globaly just create a global var and then initialized in the CameraPreview

@Shadman Adman - This is what I've understood from your comment but clearly it's wrong (it now crashes my app). The issue seems to be with previewView. I'm just not understanding how it's passed to the composable. To save time you could just edit this answer to point out what I'm doing wrong.

class MainActivity : ComponentActivity() {

    private lateinit var controller: LifecycleCameraController

    // You do not need this if you don't need to access it globalyl
    var previewView = null // is this correct?

    setContent {
      CameraApp1Theme {

        // ignore all this - just putting it here as the variables are referenced
        val resolutionSelector = ResolutionSelector.Builder()
              .setResolutionStrategy(HIGHEST_AVAILABLE_STRATEGY)
               .setAspectRatioStrategy(AspectRatioStrategy.RATIO_4_3_FALLBACK_AUTO_STRATEGY)
              .build()

        controller = remember {
           LifecycleCameraController(applicationContext).apply {
              setEnabledUseCases(CameraController.IMAGE_CAPTURE)
              setImageCaptureMode(CAPTURE_MODE_MAXIMIZE_QUALITY)
                            setImageCaptureResolutionSelector(resolutionSelector)
           }
         }
         // ignore all this - just putting it here as the variables are referenced


         CameraPreview(
            controller = controller,
            modifier = Modifier
               .align(Alignment.Center)
               .size(pwidth.dp, pheight.dp)
          )
       }
     }
}
@Composable
fun CameraPreview(
    controller: LifecycleCameraController,
    modifier: Modifier = Modifier
) {
    val lifecycleOwner = LocalLifecycleOwner.current
    val context = LocalContext.current

    val previewView = remember {
        PreviewView(context)
    }

    val screenSize = Size(9, 12)
    val resolutionSelector = ResolutionSelector.Builder()
        .setResolutionStrategy(ResolutionStrategy(screenSize, FALLBACK_RULE_CLOSEST_LOWER_THEN_HIGHER))
        .setAspectRatioStrategy(RATIO_4_3_FALLBACK_AUTO_STRATEGY)
        .build()

    AndroidView(
        factory = {
            previewView.apply {
                this.controller = controller
                controller.bindToLifecycle(lifecycleOwner)
                controller.previewResolutionSelector = resolutionSelector
            }
        },
        modifier = modifier
    )

    previewView.setOnTouchListener(handleTouch) // here?
}
发布评论

评论列表(0)

  1. 暂无评论