skiptools / skip-ui

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

Using transpiled views in purely Kotlin files #60

Open is-yusuf opened 1 month ago

is-yusuf commented 1 month ago

I was trying to add a custom marker to google maps using MarkerComposable. The custom icon is generated from swiftUI and I cannot have the content of the MarkerComposable be the customPinView as I keep getting the error java.lang.IllegalStateException: The ComposeView was measured to have a width or height of zero. Make sure that the content has a non-zero size.

My question is, what's the correct way to use a swiftUI view that got transpiled to Kotlin view in a purely Kotlin file that I use in the /skip/ folder?

aabewhite commented 1 month ago

It might help to see your code. Normally to use a SwiftUI view in a Composable function, you just do MyView(...).Compose(). If you've moved from SwiftUI to Compose and now are going back to SwiftUI, pass in a ComposeContext derived from your parent ComposeView, as in:

ComposeView { ctx in 
   ... Compose stuff ...
   MyView().Compose(ctx.content())
   ... Compose stuff ...
}
is-yusuf commented 1 month ago

Thanks for your prompt response! Here's my code setup. CustomMapView.kt: MarkerComposable( ... ) { Column { CheckInPinView("10").Compose() } } CustomPinView.swift: struct CheckInPinView: View { var waitTime: String var body: some View { ZStack{ Image("custom_pin", bundle: .module) .aspectRatio(contentMode: .fit) .frame(minWidth: 120, minHeight: 162) VStack(spacing: 0){ Text(waitTime) } } }

The CustomMapView is purely kotlin and the CheckInPinView is in Swift. Right now Only the text shows up and the image is not loaded in the android version although it is in /Resources/Resources

aabewhite commented 1 month ago

Can you try giving the image a width or height, rather than just "min"? Also where exactly is the image in the Xcode project?

is-yusuf commented 1 month ago

It's in /Sources/{AppName}/Resources/Resources.xcassets/custom_pin.imageset/Image.png I tried setting width and height and didn't work either.

is-yusuf commented 1 month ago

I believe the issue is not with finding the image. I tried the following: In swift, Instead of the Image("custom_pin"...) I used Image ("logo"...) which I used already somewhere else in the code and it works on android. However, it still didn't show the logo Image in the MarkerComposable but showed the text. I believe I'm trying to use the generated compose code in Kotlin the wrong way but I cannot find documentation on how to.

aabewhite commented 1 month ago

Does Image("custom_pin" ...) work in a SwiftUI view that is not embedded in Compose?

Can you show me how you're integrating MarkerComposable into your SwiftUI, or how you're displaying it in your app?

is-yusuf commented 1 month ago

Yes, Image(custom_pin"...) on it's own works if I write it in the swift part that gets transpiled. This is the code I have for the google map with custom markers.

GoogleMap(
        cameraPositionState = cameraPositionState,
        modifier = Modifier.fillMaxSize()
    ) {
        // Add a marker at the given location with "Hello World" as its content
        for (i in latitudeList.indices) {
            val markerPosition = LatLng(latitudeList[i], longitudeList[i])
            MarkerComposable(
                state = rememberMarkerState(position = markerPosition),
                title = "Marker at (${latitudeList[i]}, ${longitudeList[i]})",
                snippet = "Latitude: ${latitudeList[i]}, Longitude: ${longitudeList[i]}",
                onClick = {
                    openDialog.value = true
                    true
                }
            ) {
                Column {  CheckInPinView("10").Compose()}

            }
        }
        myModal(openDialog = openDialog)

    }
aabewhite commented 1 month ago

Sorry, I don't have any immediate ideas. You've tried the whole CheckInPinView and it works outside of the Compose function? How is the GoogleMap integrated into the rest of your app?

is-yusuf commented 1 month ago

Sorry for the late reply I got busy with another thing. The google map is integrated in a

#if SKIP
ComposeView { ctx in
                    GoogleMapView(kotlin.arrayOf(Double(latitude)), kotlin.arrayOf(Double(longitude)))
                }
#endif

Where GoogleMapView.kt contains

GoogleMap(
        ...
    ) {
            MarkerComposable(
                state = rememberMarkerState(position = dummyMarkerLocation),
                  ...) {
                CustomPinView("10").Compose()
            }
        }
    }

The customPinView is defined in swift and gets transpiled. currently, customPinView shows only the text and fails to load the image when called from a kotlin file, but when called from a swift file it loads the image correctly.