45

Trying to learn some new things and can't figure this one out, any help is appreciated. Given this simple code which is right from Google's documentation:

layers.xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/first_image">
      <bitmap android:src="@drawable/android_red"
        android:gravity="center" />
    </item>
    <item android:id="@+id/second_image" android:top="10dp" android:left="10dp">
      <bitmap android:src="@drawable/android_green"
        android:gravity="center" />
    </item>
    <item android:id="@+id/third_image" android:top="20dp" android:left="20dp">
      <bitmap android:src="@drawable/android_blue"
        android:gravity="center" />
    </item>
</layer-list>

And main.xml:

<ImageView
    android:id="@+myImageView"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:src="@drawable/layers" />

Question: How do I programmatically reference one of the drawables in the layer-list so I can change it to a different drawable?

Thanks.

So now I have my new drawable that I want to swap in in variable myImage correct? Now how do I get that into the layer-list? I assume I use findDrawableByLayerId and setDrawableByLayerId, but how exactly? Or I could be doing it completely wrong! Help!

What am I trying to do? Change the drawable that's displayed. For example suppose I had another drawable called "android_purple", how would I switch it in for the "android_green" drawable in the layer-list example above?

EDIT:

With my limited knowledge here is my code so far (which does not work, I get error that setDrawableByLayerId is undefined):

Resources res = getApplicationContext().getResources();
BitmapDrawable newImage = (BitmapDrawable) res.getDrawable(R.drawable.android_purple); //Get replacement image, can't use LayerDrawable or get error.   
boolean layer_drawable_changed = (setDrawableByLayerId((R.id.second_image), newImage)); //Set new drawable? Error on this line.
Jonik
  • 74,291
  • 66
  • 249
  • 356
ShadowGod
  • 7,601
  • 3
  • 25
  • 31
  • It would be better if you explain a little more elaborately exactly what you want to do ? Then it would be easier to answer your question perfectly. – Junaid Nov 05 '11 at 07:02
  • Edited question, simply trying to change the drawable in the layer-list to a different drawable. Am I making sense here? – ShadowGod Nov 05 '11 at 07:59
  • As far as i know , You can declare all your drawables in a layout-list & can define a state when to chose which drawable. The states can be like focusable state / pressed state / selected state etc etc. – Junaid Nov 05 '11 at 08:58
  • Well thinking about it a bit I figured out I can use a different layers.xml for every possible combination and just setImageResource to the appropriate layers.xml file and this works fine but I doubt is the best solution? – ShadowGod Nov 05 '11 at 10:11
  • I don't think thats the best solution you can do by creating different layout files.Instead,you should change the image resource of an imageview according to some conditions on your class using setImageResource.For example,Say,you have a variable x & you have to change the resource of an imageview according to the value of x.Suppose,if x value is 1 then setImageResource to image1.jpg,if x value is 2 then setImageResource to image2.jpg and thus goes on.I hope you understand what i wanted to say.I just wanted to say that change your image resource according to related conditions , in your class. – Junaid Nov 05 '11 at 10:33

2 Answers2

58

Question: How do I programmatically reference one of the drawables in the layer-list so I can change it to a different drawable?

Here's what I would try:

Step #1: Put android:id attributes on the <item> elements as illustrated in the documentation

Step #2: Cast the getDrawable() result to a LayerDrawable

Step #3: Call mutate() if you do not want to affect anyone else using the Drawable (may be optional)

Step #4: Call setDrawableByLayerId() to set/replace a Drawable for a given layer ID

CommonsWare
  • 910,778
  • 176
  • 2,215
  • 2,253
  • Thank you. What you are saying is what I'm trying but it's not working. I'm beginning to think it's not possible. The only way I've found to do what I want is to change the ImageView source to an entirely new layers.xml file that contains the drawables I want. If I'm making any sense... – ShadowGod Nov 06 '11 at 07:35
  • Updated question with what I'm trying. – ShadowGod Nov 06 '11 at 09:43
  • 1
    @ShadowGod: Don't use `getApplicationContext()` for GUI-related stuff. That being said, I tend to agree with Junaid, that there may be more effective solutions for what you're trying to accomplish here. – CommonsWare Nov 06 '11 at 21:55
  • Ok thanks. As a beginner I just didn't think what I am trying to do would be such a big deal and that hard to accomplish. I appreciate the help. – ShadowGod Nov 06 '11 at 22:04
  • Just a final note for other beginners that may be reading this: I have discovered that what I was ultimately trying to do here, layer graphics for a user interface, is easier done with a RelativeLayout nested inside a FrameLayout. – ShadowGod Nov 10 '11 at 09:48
  • 1
    @ShadowGod: I'm not quite certain why you needed the nesting necessarily, as `RelativeLayout` supports Z-axis ordering on its own. Later children of a `RelativeLayout` stack over top of earlier children. Regardless, I'm glad to hear that you have this working! – CommonsWare Nov 10 '11 at 22:32
  • So, you gave up? Bummer! I am trying to do the same thing now; but no matter what I do, the bitmap that is the backmost layer gets removed when I call setDrawableByLayerId. – Glenn Bech Jun 05 '12 at 22:18
  • @CommonsWare Hello sir one issue in this code if I can make to create the round corner imageView using Layer-list. in this layer-list first is one drawable image and another is roundcorder shape drawable xml file.when I try to use this code according to change the layer drawable work perfect but the rounded drawbable not set proper of the image. – Zala Janaksinh Aug 08 '14 at 12:31
  • @ZalaJanaksinh: Sorry, but I do not know what you mean. Please ask a fresh Stack Overflow question, providing the code that is giving you problems and screenshots of what you are seeing. – CommonsWare Aug 08 '14 at 12:32
  • @CommonsWare sir not any error in code but using this code i can't achieve proper result. – Zala Janaksinh Aug 08 '14 at 12:34
  • Calling `mutable()` is important when you use the same layer drawable in multiple places , since the item has same id. – Libin Nov 11 '17 at 16:30
  • Possible to center the bitmap you insert. IE, how can you programmatically do this: ...> – lostintranslation Apr 14 '18 at 21:36
  • @lostintranslation: I do not know, sorry. – CommonsWare Apr 14 '18 at 22:24
  • Is it possible to do same thing directly in XML code rather then java – Chirag Gupta Jun 25 '20 at 09:41
55

Step 1:Retrieve the Layer-list from the drawable folder: (Mine was called digits at /res/drawable/digits.xml)

LayerDrawable ld = (LayerDrawable) getResources().getDrawable(R.drawable.digits);

Step 2: Name the replacing image (not the the image already in layer-list)

Drawable replace = (Drawable) getResources().getDrawable(R.drawable.replacing_image);

Step 3: Replace the Image using the setDrawableByLayerId(int id, Drawable d) method

boolean testfactor = ld.setDrawableByLayerId(R.id.first_image, replace);

This returns a boolean value that will return false if replacing the image failed

Step 4: Load main Imageview (basically id of layer-list in the actual xml layout code)

ImageView layoutlist1 = (ImageView)findViewById(R.id.layout_list1);

Step 5: (re)-Set the Imageview with your updated LayerDrawable by saying:

layoutlist1.setImageDrawable(ld);

RESOURCES: I'm a software and mobile app developer.

I looked all over the web and alot of Stackflow.com in order to get to this point. All the answers were like the ones that were already on this page. I was trying to do the same thing. Then I thought about the idea of "updating the image" and came to this.

This should/can also work for when you want to put a Bitmap in place of one the items on your list. You just have to use the replace (setDrawableByLayerId) method. to replace on ids. ImageView has a lot of methods.

This was also helpful: LayerList drawable + conversion to a Bitmap

Darshana
  • 2,366
  • 6
  • 25
  • 49
Kavita
  • 650
  • 5
  • 5
  • 1
    Thank you [D-R](http://stackoverflow.com/users/1244383/d-r) for help with formatting my response/fixing my link at the bottom. I just joined recently because I wanted to add this response when I was frustrated with the answers available – Kavita Jun 14 '12 at 13:24
  • is this method a memory hog? i need to set rounded image in a recyclerview – filthy_wizard Jul 11 '16 at 09:02