Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jetpack Compose: Custom VectorAsset Icon object similar to built-in `Icons.Default`

It looks like the only way to go about loading custom icons from Android Vector Resources in the res folder is to do it within a @Composable function using the vectorResource(R.drawable.myVectorName) method.

This is great and all, but I like the syntax of fetching VectorAssets for the Icon(asset: VectorAsset) class, which looks like Icon(Icons.Default.Plus).

It looks like the vectorResource() method uses an internal method called loadVectorResource(), and the methods it uses to read the actual XML file composing the vector asset file are also internal.

How would I go about creating an object like MyAppIcons.Default.SomeIcon in Jetpack Compose?

EDIT

So, I have sort-of found a solution. However, it would be nice to make my own extension/overloading of the built-in Icon() function, but I'm not sure if there is a proper way to do this.

like image 530
foxtrotuniform6969 Avatar asked Nov 05 '20 15:11

foxtrotuniform6969


2 Answers

Turns out I wasn't using my brain. The answer is pretty easy.

The gist is, Icon() is a composable function, meaning that of course vectorResource() can be used there.

So, the correct approach is no secret... it's to make your own MyAppIcon() component, call vectorResource() and then return a normal Icon(), like so:

Correct Way

@Composable
fun MyAppIcon(
    resourceId: Int,
    modifier: Modifier = Modifier,
    tint: Color = AmbientContentColor.current
) {
    Icon(
        asset = vectorResource(id = resourceId),
        modifier = modifier,
        tint = tint
    )
}

You can then create an object elsewhere, like so:

object MyAppIcons {
    val SomeIcon = R.drawable.someIcon
    val AnotherIcon = R.drawable.anotherIcon
}

When you put the two together, you can use it like this:

MyAppIcon(MyAppIcons.SomeIcon)

I'm hoping that Google just adds this override soon, allowing us to pass in resource IDs.

like image 92
foxtrotuniform6969 Avatar answered Sep 21 '22 04:09

foxtrotuniform6969


from Resources in Compose

Use the painterResource API to load either vector drawables or rasterized asset formats like PNGs. You don't need to know the type of the drawable, simply use painterResource in Image composables or paint modifiers.

// Files in res/drawable folders. For example:
// - res/drawable-nodpi/ic_logo.xml
// - res/drawable-xxhdpi/ic_logo.png

// In your Compose code
Icon(
    painter = painterResource(id = R.drawable.ic_logo),
    contentDescription = null // decorative element
)
like image 35
yazan sayed Avatar answered Sep 19 '22 04:09

yazan sayed