0

In my app I am using this function to return a Drawable witch changed color:

fun setDrawableColor(icon: Drawable, color: Int): Drawable {
    val drawable = DrawableCompat.wrap(icon)
    DrawableCompat.setTint(drawable, getColor(color))
    return drawable
}

This works perfectly. However, I can't use it for example for setIcon() of a AlertDialog since it takes a Drawable as Integer like this setIcon(R.dawable.my_icon).

I need a similar function like above one, which does exactly the same thing but returns Drawable as Integer instead. How can I achieve that?

halfer
  • 19,824
  • 17
  • 99
  • 186
Mark Delphi
  • 1,376
  • 1
  • 11
  • 29
  • You're not going to be able to do that. That `R.drawable` refers to resource from which a `Drawable` is created, and that's a one-way operation. You can't reverse a `Drawable` back to a resource, and then assign it an ID, one reason for which is that you cannot create resources at runtime. I would mention, though, that `AlertDialog` does have [a `setIcon(Drawable)` method](https://developer.android.com/reference/android/app/AlertDialog#setIcon(android.graphics.drawable.Drawable)), which takes a `Drawable` rather than an `R.drawable`. – Mike M. May 25 '20 at 04:49
  • There is no direct function to do this, Why don't you directly pass the drawable instead of int? If you want to pass the drawable name as parameter then there's a way: https://stackoverflow.com/a/13115927/2462531 – Shailendra Madda May 25 '20 at 04:55
  • The proposed solution by @ShylendraMadda works good. Please see it below. – Mark Delphi May 25 '20 at 09:54
  • That's not doing what you might think it is. By default, `Drawable` instances created from the same resource will share a common, cached state, unless explicitly configured otherwise. That example is basically loading a `Drawable` from that resource, creating a common state for it, but then just discarding the `Drawable` itself. That cached state is what's causing the separate `Drawable` instance created by the `AlertDialog` to have the given tint. The resource ID lookup isn't doing anything, as you could accomplish the same thing by passing around the `R.drawable.my_icon` you used to... – Mike M. May 25 '20 at 10:55
  • ...create the `Drawable` in the first place. That is, you could simply create the `Drawable` from `R.drawable.my_icon` first, call your `setDrawableColor()` method, and then call `AlertDialog#setIcon(R.drawable.my_icon)`. If you're only showing that particular icon once at any given time, it might work for ya, but there are other, arguably preferable, solutions; e.g., using the `setIcon(Drawable)` method instead. Indeed, most every framework method that would take a drawable resource ID has an overload that takes a `Drawable` instance instead. – Mike M. May 25 '20 at 10:55
  • @MikeM. Many thanks for your effort and explanation. What said is also valid, but nevertheless I could solve that problem. However, there was not problem, I just needed to have two same drawables with different colors. Using that way, I can use only one drawable and change its color according to use case. – Mark Delphi May 25 '20 at 12:52
  • I don't think you're following what I'm saying. What I'm describing doesn't have anything to do with number of `Drawable`s. I'm saying, the example below is just your code with a `resources.getIdentifier()` call added. That `resources.getIdentifier()` is completely pointless, because it's always going to return the same: `R.drawable.my_icon`'s value. You comment below that "it does not look to be an elegant solution, since you have to pass the drawable name as parameter". You don't have to pass the name, 'cause the returned value is always `R.drawable.my_icon`, which you can just use instead. – Mike M. May 25 '20 at 13:00
  • (Obviously, if you pass it a different name, you'll get that different `R.drawable`'s value, instead. I was just using `R.drawable.my_icon` as a concrete example here.) – Mike M. May 25 '20 at 13:16
  • @MikeM. no idea bro, I did not test it as you did, it just does what I expected and probably, I will try to find another solution. – Mark Delphi May 25 '20 at 19:04

1 Answers1

0

You can try this way but you need to pass the drawable name as parameter here

fun getDrawableColorAsInt(icon: Drawable, color: Int, drawableName: String): Int {
        val drawable = DrawableCompat.wrap(icon)
        DrawableCompat.setTint(drawable, context!!.getColor(color))
        val resourceID = resources.getIdentifier(drawableName, "drawable", context!!.packageName)
        return resourceID
    }
Shailendra Madda
  • 20,649
  • 15
  • 100
  • 138
  • Thank you very much for your response. Your solution works, however, it does not look to be an elegant solution, since you have to pass the drawable name as parameter. Nevertheless, it works. Thanks! – Mark Delphi May 25 '20 at 09:54
  • I have an issue now, it does not work for Android Marshmallow and below. Any ideas bro, how to enforce it to work on those Android versions? Thanks! – Mark Delphi Jun 10 '20 at 22:35