Estou trabalhando na criação de uma experiência de "integração" para meu aplicativo, que é essencialmente um guia rápido sobre como usar o aplicativo. Para conseguir isso, quero que o usuário clique onde o aplicativo o instrui. Especificamente, gostaria de criar uma interface de usuário com um elemento circular onde o usuário possa clicar e um fundo cinza transparente onde o clique não seja permitido (consulte a imagem em anexo para maior clareza)
Meu desafio atual consiste em descobrir como propagar esse evento de clique para as camadas inferiores da UI.
Aqui está o trecho de código relevante:
Canvas(
modifier = Modifier
.fillMaxSize()
.zIndex(3f)
.pointerInput(Unit) {
detectTapGestures(onTap = { offset ->
if (!Rect(position, volume).contains(offset)) {
Log.d("app-debugger9","Cancel the click!")
}
else
{
Log.d("app-debugger9","Propagate click to below UI layers!")
}
})
}
) {
val circlePath = Path().apply {
addOval(Rect(position, volume))
}
clipPath(circlePath, clipOp = ClipOp.Difference) {
drawRect(SolidColor(Color.Black.copy(alpha = alphaValue)))
}
}
Log.d("app-debugger9", "Propagar clique para as camadas inferiores da UI!") - Esta instrução Log.d indica o momento em que pretendo propagar o evento de clique para as camadas inferiores da UI. Minha pergunta é: como posso conseguir isso?
Atualmente, não importa onde eu clique, dentro ou fora do círculo, não consigo propagar esse clique para a camada inferior da interface do usuário.
O que espero é que, se clicar fora do círculo, o clique seja ignorado. Porém, se eu clicar dentro do círculo, o clique será propagado para a camada inferior da UI, o que leva à abertura de um nível (porque esse círculo está posicionado acima do botão de abertura do nível).
Nota: 1) É possível que isso seja feito sem usar 'pointerInput(Unit)', mas não tenho certeza de como fazer isso, então optei por usar 'pointerInput(Unit)' por enquanto. 2) Quando me refiro às camadas de UI 'acima' ou 'inferiores', estou usando .zIndex(). Se o índice for maior, significa 'acima', e se o índice for menor, significa 'inferior'.
Com Modifier.clickable ou PointerEventScope.detectTapGestures você não pode propagar gestos para descendente ou pai porque eles chamam
PointeEventChange.consume()
, você pode verificar esta resposta sobre gestos e propagação de gestos no Jetpack Compose. Mas no seu caso parece que você está tentando propagar um evento para o qual não é possível e um design ruim na minha opinião.Para qualquer pessoa que queira passar um gesto para o pai e não para o irmão, você pode facilmente escrever um gesto personalizado de detecção para cima e para baixo usando
awaitEachGesture
.Dependendo do zIndex de Box1 e Box2 você verá que o evento será acionado para aquele com zIndex maior, se ambos zero, que é zero por padrão, serão acionados para a segunda caixa e então propagados para o pai. Você pode alterar isso seletivamente consumindo qualquer um deles
PointerInputChange
.No caso dos PO, não há necessidade de uma segunda caixa. A camada transparente preta com clipe circular pode ser desenhada usando Modifier.drawWithContent e com base na posição de toque você aciona o evento de clique nesta camada ou em qualquer componente.
Você pode ver que enquanto os gestos de toque são consumidos, a menos que você consuma, os gestos são propagados.