4

By default all the Composables, much like views are defined in form of Rects, i.e., four specific corner points with distinct properties. Now, if I want to implement something like this

custom composable with merged clickables

(This is just an example, I want to implement this with much complex shapes (PATHS using Canvas))

So, when the user clicks on either of the triangles, the specific codeblock implemented for that triangle should be executed.

I got almost no possible approaches to this, so please inform if anyone does, thanks!

Ryan M
  • 18,333
  • 31
  • 67
  • 74
Richard Onslow Roper
  • 5,477
  • 2
  • 11
  • 42
  • Interesting, I wasn't been able to find any Compose way to define touch region. In the worst scenario you can detect click position with `pointerInput` and decide wether you need to handle the click based on touch position. But I think there should be system way of doing that, like SwiftUI has [`contentShape`](https://developer.apple.com/documentation/swiftui/view/contentshape(_:eofill:)) to define clickable region. – Phil Dukhov Oct 24 '21 at 07:19
  • Actually, you have. You just couldn't connect the dots. I got a plausible solution from one of your other answers, Dr. Dukhov. – Richard Onslow Roper Aug 24 '22 at 08:43
  • You can check out this answer [here](https://stackoverflow.com/questions/73416175/jetpack-compose-split-a-card-diagonally-and-put-content-inside-them/73416472#73416472) clipping with a shape will also clip touchable area either. – Thracian Aug 24 '22 at 08:51
  • Every upvote has an equal and opposite reaction... I learn something new everyday. – Richard Onslow Roper Aug 24 '22 at 08:56
  • This was the plausible solution I was referring to, by Mr. Dukhov. He has posted several answers explaining custom clipping of containers like `Box`, but he couldn't connect that the clickable areas are clipped too, which is exactly what was required to solve this question, which is illustrated by Dr. Thracian's answer here. – Richard Onslow Roper Aug 24 '22 at 08:58
  • @Thracian Oh I learned that from Dr. Dukhov again, [here](https://stackoverflow.com/q/68976134/15880865) – Richard Onslow Roper Aug 24 '22 at 08:59

1 Answers1

3

You can accomplish it by creating a custom shape and applying the image that is drawn latest in a Box

@Composable
private fun DividedImage() {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(200.dp)
    ) {

        val context = LocalContext.current

        val shapeLeft = GenericShape { size: Size, layoutDirection: LayoutDirection ->
            val width = size.width
            val height = size.height
            moveTo(0f, 0f)
            lineTo(0f, height)
            lineTo(width, height)
            close()
        }

        val modifierLeft = Modifier
            .fillMaxWidth()
            .height(200.dp)
            .graphicsLayer {
                clip = true
                shape = shapeLeft
            }
            .clickable {
                Toast
                    .makeText(context, "LEFT", Toast.LENGTH_SHORT)
                    .show()
            }
            .border(3.dp, Color.Green)


        val modifierRight = Modifier
            .fillMaxWidth()
            .height(200.dp)

            .clickable {
                Toast
                    .makeText(context, "RIGHT", Toast.LENGTH_SHORT)
                    .show()
            }
            .border(3.dp, Color.Red)



        Image(
            modifier = modifierRight,
            painter = painterResource(id = R.drawable.landscape2),
            contentDescription = null,
            contentScale = ContentScale.FillBounds
        )

        Image(
            modifier = modifierLeft,
            painter = painterResource(id = R.drawable.landscape1),
            contentDescription = null,
            contentScale = ContentScale.FillBounds
        )
    }
    
}

enter image description here

Thracian
  • 43,021
  • 16
  • 133
  • 222
  • Really leaning in on that equal and opposite reaction thing huh... ok. – Richard Onslow Roper Aug 24 '22 at 09:05
  • Just wondering,,, should I remove this question, because now that I think about it the one that you linked is almost exactly the same. Doesn't explain the problem quite as well, but is essentially the same. – Richard Onslow Roper Aug 24 '22 at 09:11
  • Your question asks for a click version either which is not present in other question. Probably many people don't know order of modifier click and graphicsLayer changes how a Composable is structured. You can check out my question here to see it clearly how setting clip and touch changes what you get as a result https://stackoverflow.com/questions/72922205/how-to-have-natural-pan-and-zoom-with-modifier-graphicslayer-pointerinput – Thracian Aug 24 '22 at 09:12
  • Yeah many would be wondering about this, I mean the click specifically. Now, just letting this question be, is better than trying to convince the other poster (OP, haha) to edit theirs out. So, get happy, Dr. Thracian. You've got the reputation your heart desires. Muahahahaha – Richard Onslow Roper Aug 24 '22 at 09:15