dotnet / dotnet/android-libraries
Compose: painterResource(Int, Composer) not bound in Xamarin.AndroidX.Compose.UI.Android (PainterResources_androidKt wrapper is empty)
- Dominant language
- C#
- Stars
- 317
- Forks
- 73
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 17
Description
## Summary
`Painter` and the painter implementations (`BitmapPainter`, `BrushPainter`, `ColorPainter`) **are** bound in `Xamarin.AndroidX.Compose.UI.Graphics`, but the loader `painterResource(@DrawableRes id: Int): Painter` from `androidx.compose.ui.res.PainterResources_androidKt` is not reachable from C# — only an empty `PainterResources_androidKt` wrapper class is emitted, with zero static methods.
Without `painterResource`, the bound `Painter` types are unreachable from typical Compose code (`Image(painter = painterResource(R.drawable.foo), …)`).
## Library / NuGet
- AAR: `androidx.compose.ui:ui-android` (the `Kt` class lives here, not in `ui-graphics-android`)
- NuGet: `Xamarin.AndroidX.Compose.UI.Android`
- Source dir: [`source/androidx.compose.ui/ui-android/`](https://github.com/dotnet/android-libraries/tree/main/source/androidx.compose.ui/ui-android)
## Verified state today (commit eb2f50b)
`source/androidx.compose.ui/ui-android/PublicAPI/PublicAPI.Unshipped.txt` contains exactly two `PainterResources_androidKt` lines:
```
AndroidX.Compose.UI.Res.PainterResources_androidKt
override AndroidX.Compose.UI.Res.PainterResources_androidKt.JniPeerMembers.get -> Java.Interop.JniPeerMembers!
```
…i.e. the class wrapper is bound but **no `painterResource` static method is exposed**. The Kotlin function is:
```kotlin
@Composable
@ReadOnlyComposable
fun painterResource(@DrawableRes id: Int): Painter
```
There is no `@JvmInline value class` parameter, so this is **not** the same hash-mangled-name pattern as [dotnet/java-interop#1440](https://github.com/dotnet/java-interop/pull/1440). The `@Composable` annotation alone causes the JVM signature to include trailing `Composer` + `Int $changed` parameters, but those bind fine elsewhere. Something more specific is dropping this overload — likely the `@ReadOnlyComposable` attribute or the `Painter` return type's nullability/inheritance metadata.
For comparison, `Painter` itself binds fine in `Xamarin.AndroidX.Compose.UI.Graphics`:
```
AndroidX.Compose.UI.Graphics.Painter.Painter
abstract AndroidX.Compose.UI.Graphics.Painter.Painter.IntrinsicSize.get -> long
virtual AndroidX.Compose.UI.Graphics.Painter.Painter.ApplyAlpha(float alpha) -> bool
virtual AndroidX.Compose.UI.Graphics.Painter.Painter.ApplyColorFilter(AndroidX.Compose.UI.Graphics.ColorFilter? colorFilter) -> bool
…
AndroidX.Compose.UI.Graphics.Painter.BitmapPainter
AndroidX.Compose.UI.Graphics.Painter.BrushPainter
AndroidX.Compose.UI.Graphics.Painter.ColorPainter
```
## Metadata.xml today
`source/androidx.compose.ui/ui-android/Transforms/Metadata.xml` has surgical removes for inline-class hash-mangled overloads but nothing referencing `painterResource` / `PainterResources_androidKt`. The method is being dropped by the binder itself, not by the project's transforms.
## Reproduction / evidence
`compose-net` works around this with a hand-written JNI bridge:
- [`ComposeBridges.cs`](https://github.com/jonathanpeppers/compose-net/blob/main/src/ComposeNet.Compose/ComposeBridges.cs) – `[ComposeBridge(Class = "androidx/compose/ui/res/PainterResources_androidKt", JvmName = "painterResource", Signature = "(ILandroidx/compose/runtime/Composer;I)Landroidx/compose/ui/graphics/painter/Painter;")]`
The bridge calls successfully at runtime and returns a usable `Painter` handle, so the underlying Java method exists and behaves correctly — only the binding-time projection is missing.
## Suggested fix
Add the `painterResource(int, Composer, int)` static to `AndroidX.Compose.UI.Res.PainterResources_androidKt`. If it can't be generated automatically, an `add-node` transform in `Transforms/Metadata.xml` should suffice.
## Cross-references
- compose-net tracking: none filed yet (Painter usage is documented in [`src/ComposeNet.Compose/Image.cs`](https://github.com/jonathanpeppers/compose-net/blob/main/src/ComposeNet.Compose/Image.cs))
- Master inline-class blocker: [dotnet/java-interop#1440](https://github.com/dotnet/java-interop/pull/1440) — **note**: `painterResource` does **not** appear blocked on #1440 because it has no inline-class parameters.
Contributor guide
Assessment
This issue has not been assessed yet.