skiptools / skip-ui

SwiftUI for Android
https://skip.tools
GNU Lesser General Public License v3.0
119 stars 12 forks source link

TapGesture is not working with Path or Shape #28

Open jumartin opened 6 months ago

jumartin commented 6 months ago

This is fine on iOS but not on Android (skip 0.8.28 / skip-ui 0.6.2) :

struct CustomShape: Shape {
    var angle: CGFloat
    var s = 30.0

    func path(in rect: CGRect) -> Path {
        let r = min(rect.width, rect.height) / 2.0
        let c = CGPoint(x: rect.midX + r*cos(angle), y: rect.midY + r*sin(angle))
        return Path(ellipseIn: CGRect(x: c.x - s, y: c.y - s, width: s*2.0, height: s*2.0))
    }
}

struct ContentView: View {
    var body: some View {
        ZStack {
            ForEach(0..<8) { n in
                let angle = Double.pi * 2.0 / 8 * CGFloat(n)
                CustomShape(angle: angle)
                    .fill(.green)
                    .onTapGesture {
                        logger.log("tapped \(n)")
                    }
            }
        }
    }
}

It is the same with Path - on Android the message is logged even when tapping outside the shape :

struct ContentView: View {
    var body: some View {
        Path { p in
            p.move(to: CGPoint(x: 100, y: 0))
            p.addLine(to: CGPoint(x: 200, y: 200))
            p.addLine(to: CGPoint(x: 0.0, y: 200))
        }
        .fill(.green)
        .onTapGesture {
            logger.log("tapped inside path")
        }
    }
}
aabewhite commented 6 months ago

Sorry for the trouble, and thanks for the report. Just to clarify, the issue is only that the tap is registering is space outside the filled area, correct?

jumartin commented 6 months ago

Yes. In both examples, the tap gesture on Android is not constrained to the shape. Thanks!

aabewhite commented 6 months ago

I was able to play with this a little, and while I don't have a fix yet, I do have a workaround:

CustomShape() .fill(...) .onTapGesture { ... } .clipShape(CustomShape())

That seems to work for me. Hopefully this workaround can allow you to move forward until we have a full solution!

jumartin commented 6 months ago

Thanks for the workaround. It works fine indeed! 👍

aabewhite commented 6 months ago

skip-ui 0.6.3 is now available. If you update by using Xcode's File->Packages->Update to Latest, you should be able to remove your workaround. Please let us know if you have any issues!

jumartin commented 6 months ago

Thanks. That actually worked fine until I upgrade to skip 0.8.29. Now I get weird shapes - though the tap gesture works as expected without the workaround.

Expected result (iOS) Simulator Screenshot - iPhone 15 - 2024-04-06 at 21 39 38

Android (skip 0.8.29 / skip-ui 0.6.3) Screenshot_20240406_214447

aabewhite commented 6 months ago

Well that's not good! Do you mind posting the code you're drawing with? I'll work on it tonight

aabewhite commented 6 months ago

I'll have the fix ready within a day. For now you should be able to get the shapes back to normal by inserting a .id() modifier between the .fill and the .onTapGesture.

jumartin commented 6 months ago

Thanks. If I add .id("shape\(n)"), shapes are indeed back to normal, but then the tap gesture is not working properly again (unless I add the .clipShape(...) workaround).

aabewhite commented 6 months ago

Yes, that's as expected. I'll have a proper fix for you by the end of today. Sorry for the trouble!

aabewhite commented 5 months ago

OK I've just pushed 0.6.4

It should fix the issue. And I've added additional information to the Gestures section of the SkipUI README with its limitations: https://github.com/skiptools/skip-ui/blob/main/README.md#gestures

Pease let us know if you have any issues or additional requests!

jumartin commented 5 months ago

Great, thanks!