简体   繁体   中英

Android Drawable XML - setting the src programmatically?

I have a drawable XML resource with this content:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/backgroundImage"
    android:src="@drawable/london"
    android:gravity="center"></bitmap>

My portrait and landscape activity layout uses this resource as a background image:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/centered_bg">
    ...

Now I try to update the drawable XML bitmap's src attribute programatically, but the only thing I can think of is casting the view into an ImageView:

private void updateBackgroundImage() {
    Drawable backgroundImage = CityBackgrounds.getCityBackground(this, curCity.ID);
    if (backgroundImage != null) {
        ImageView backgroundObj = (ImageView) findViewById(R.id.backgroundImage);
        backgroundObj.setImageDrawable(backgroundImage);
    }
}

This doesn't work as backgroundObj is null and so a RuntimeException occurs.

I don't know how to reference a Bitmap xml object to change the src attribute or if it's even possible.

How can I switch the layout backgrounds without making all the objects on the layout overlap an ImageView filling the background?

I ended up doing it like this:

private static final String BACKGROUND_XML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"+
        "<bitmap xmlns:android=\"http://schemas.android.com/apk/res/android\""+
        "    android:id=\"@+id/backgroundImage\""+
        "    android:src=\"@drawable/%s\""+
        "    android:gravity=\"center\"></bitmap>";

private void updateBackgroundImage() {
    View view = findViewById(R.id.portrait_layout);
    try {
        XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
        parser.setInput(new StringReader(String.format(BACKGROUND_XML, curCity.ID)));
        view.setBackground(Drawable.createFromXml(getResources(), parser));
    } catch (XmlPullParserException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Trying to create the XML resource on the fly. However, this results in a class cast exception from an Android library class, which has a message comment explaining that this feature is not currently supported (so I guess the class-cast exception was intended):

  Caused by: java.lang.ClassCastException: android.util.XmlPullAttributes cannot be cast to android.content.res.XmlBlock$Parser at android.content.res.Resources.obtainAttributes(Resources.java:2830) at android.graphics.drawable.Drawable.inflate(Drawable.java:1207) at android.graphics.drawable.BitmapDrawable.inflate(BitmapDrawable.java:723) at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:1150) at android.graphics.drawable.Drawable.createFromXml(Drawable.java:1063) at android.graphics.drawable.Drawable.createFromXml(Drawable.java:1041) at com.giraffeweather.WeatherActivity.updateBackgroundImage(WeatherActivity.java:389) 

android.content.res.Resources.java:

public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
    int len = attrs.length;
    TypedArray array = TypedArray.obtain(this, len);

    // XXX note that for now we only work with compiled XML files.
    // To support generic XML files we will need to manually parse
    // out the attributes from the XML file (applying type information
    // contained in the resources and such).
    XmlBlock.Parser parser = (XmlBlock.Parser)set;
    mAssets.retrieveAttributes(parser.mParseState, attrs,
            array.mData, array.mIndices);

    array.mXml = parser;

    return array;
}

I'm not sure if the message indicates using the alternative method where you give the AttributeSet it should work. Will update answer once I've tried it.

It doesn't seem like you need to create an XML bitmap if all it does is reference another drawable. What you can do is set your RelativeLayout background to @drawable/london , then when you need to change the background of your layout, call setBackground(Drawable) on the root view of your layout, in this case, the RelativeLayout

In order to apply different drawable in portrait / landscape mode you can just use the android already existing mechanism for resources.

images are located at

  • res/drawable-hdpi
  • res/drawable-mdpi

etc. (these are the default folders)

for images that should applied in landscape mode use folders

  • res/drawable-hdpi-land
  • res/drawable-mdpi-land

etc. (by applying the qualifier land the system automatically picks drawables for landscape)

in case you want to specify for portrait it is used the port qualifier

Same drawables should have the same name in all folders in order to picked correctly, more about that at android documentation


Edit.

Instead of using the XML format of bitmap drawable you can use the BitmapDrawable class. That way you create an image with center gravity and then set it to background.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM