I have need of a pointer modifier that can filter ...
# compose
t
I have need of a pointer modifier that can filter pointer events based on satisfying an arbitrary geometric constraint (e.g. where is the pointer at on the view), detect if it's a tap in that location, and otherwise let the event fall through. So one could imagine an arbitrary shape like a star or a trapezoid or a circle, right the function that determines whether a point is in that shape, consume it if it is, let it pass on if it isn't, and if it is see if it's a tap. To that end, I've written modifier extension, attached in thread. It's working. I'm curious to get feedback from all you experts if this is a good way to do this or not.
Copy code
@OptIn(ExperimentalComposeUiApi::class)
fun Modifier.maskPointerBy(predicate: (Offset, Size) -> Boolean, onTap: () -> Unit = {}): Modifier = composed(inspectorInfo = debugInspectorInfo {
    name = "maskPointerBy"
    properties["predicate"] = predicate
    properties["onTap"] = onTap
}) {
    var downAt: Offset? = remember { null }
    val threshold = with(LocalDensity.current) { 20.dp.toPx() }
    val view = LocalView.current
    pointerInteropFilter { event ->
       val eatEvent = predicate(Offset(event.x, event.y), Size(view.width.toFloat(), view.height.toFloat()))
       if (eatEvent) {
          when (event.action) {
             ACTION_DOWN -> downAt = Offset(event.x, event.y)
             ACTION_UP -> {
                downAt?.let { downAt ->
                   val distance = ((downAt.x - event.x).pow(2) + (downAt.y - event.y).pow(2)).pow(0.5f)
                   if (distance <= threshold) {
                      onTap()
                   }
                }
                downAt = null
             }
          }
       }
       eatEvent
    }
}
I should add, I found no way to do this without using the interop filter