Skip to content

Compose: painterResource(Int, Composer) not bound in Xamarin.AndroidX.Compose.UI.Android (PainterResources_androidKt wrapper is empty) #1443

@jonathanpeppers

Description

@jonathanpeppers

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

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:

@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. 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[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

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions