Shape drawable in layer-list rendered incorrectly for APIs below 23
Asked Answered
P

1

13

Yesterday, I've switched to Android Studio version 2.1.3. Today, I've re-opened one of my projects and tried to add some layer-list drawables for use with an ImageView. For example this one:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:width="80px" android:height="80px"
        android:top="0px" android:left="0px" 
        android:right="0px" android:bottom="0px">
        <shape android:shape="rectangle">
            <solid android:color="@color/deep_orange"/>
        </shape>
    </item>
    <item android:width="60px" android:height="60px"
        android:top="10px" android:left="10px" 
        android:right="10px" android:bottom="10px">
        <shape android:shape="oval">
            <solid android:color="@color/light_yellow"/>
        </shape>
    </item>
</layer-list>

yellow circle above orange square

This is what I used to get before upgrading my Android Studio version, and this is what I get now in the Preview if I choose 23 as "Android version to use when rendering layouts in the IDE".

However, if I choose any version below 23, I get just the square:

orange square, no circle

Unfortunately, I also get nothing but the square when running the app on an emulator (Lollipop 22) or a device (Jellybean 18).

Just in case this is helpful:

  • compileSdkVersion 23
  • buildToolsVersion "23.0.3"
  • minSdkVersion 11
  • targetSdkVersion 23
  • nothing for buildType debug
  • dependencies: compile 'com.android.support:appcompat-v7:23.0.1'
  • the Activity extends AppCompatActivity

I think the problem is somehow related to the use of top, left, right and bottom for the upper layer. Because if I simply place a circle on top of a square, the preview as well as the "real thing" work as expected for all API levels.

EDIT I also started a brand new project with the same code/ xml and the following (automatically created) build.gradle:

  • compileSdkVersion 24
  • buildToolsVersion "24.0.2"
  • minSdkVersion 15
  • targetSdkVersion 24
  • nothing for buildType debug
  • dependencies: compile 'com.android.support:appcompat-v7:24.2.0'
  • the Activity extends AppCompatActivity

The same behaviour here: the upper layer is not rendered for API leves <= 22 if I use top, left, right and bottom with values != 0.


So my question is: how can I create shape drawables "with insets" for all API levels using Android Studio 2.1.3?

Pantomime answered 9/9, 2016 at 11:28 Comment(16)
what if you set top and others to: android:top="0px" ?Aerodyne
@Aerodyne - if I do this for the upper layer, then in the preview for 23 I get a 60px diameter circle in the top left corner above an orange square (80px), for 22 I get both shapes stretched to maximum in the (rectangular) preview. On my (22) emulator, the drawable fills the ImageView (80dp x 80dp)Candlelight
just run on 6.0 emulator: <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/chrome"/> <item android:drawable="@drawable/mask_orig" android:left="20dp" android:top="20dp" android:right="20dp" android:bottom="20dp"/> </layer-list> and it worked fineAerodyne
@Aerodyne - yes, that's just the point: 6.0 = API level 23, so no problem. But for Lollipop or Jellybean, I get no upper layer :(Candlelight
oh, right sorry, trying 5.0 now...Aerodyne
works like a charm on 5.0 as well so it is not a problem of layer-listAerodyne
@Aerodyne - I think it's something about the "new" Android Studio installation. Maybe some libraries which don't match. After all, AS recommends sometimes using a newer library (24-something) for a compileSdk-23...project, only to state that this isn't possible right after I follow its suggestion.Candlelight
did you try my xml?Aerodyne
@Aerodyne - I did now. It works, so I think the problem is not so much with layer-list but more with shape drawable inside layer-list.Candlelight
exactly! try removing android:width / android:height firstAerodyne
@Aerodyne - without any width/ height: the "old" project (compileSdk=23) looks the same, the "new" project (compileSdk=24) now even does not draw the circle for API level 23 preview. "Our situation has not improved" :(Candlelight
try this LayerDrawable then, now you will know if it has anything to do with your xml build toolsAerodyne
@Aerodyne - first: thank you very much for your help, I really appreciate it :) About the last drawable: well, I get an orange square (scaleType centerCrop) I suppose that's not optimal. But I think I finally managed to solve my shape drawable problem, actually quite by accident: (cont)Candlelight
(cont) I stumbled across this: Starting from API 23, it is possible to set width and height right within the "item" tag, and I realized that's what I've been doing: I set height and width to the item but not to the shape. So I added <size.../> to the shapes and everything was fine :). I think I missed it all the time because my earlier AS (1.4, which I did not dare to upgrade because last time it took me a week to get the old projects running again) would have complained (I've only used compileSdk = 22 before) but the new one didn't.Candlelight
@Aerodyne - (cont II) So once more: thanks for your help! If you like, you can write the answer and I'll be glad to accept and upvote.Candlelight
well, what should i write in the answer as it was you who found out whats wrong, glad it works now anyway... (btw did you call GradientDrawable#setSize(int width, int height) to find it out?)Aerodyne
P
16

First of all, I'd like to thank @pskink for helping me to analyse the problem :)

The xml in the question worked for API level 23+, because

it is possible to set width and height right within the "item" tag

like @android developer states in this SO post

It did not work for lower versions, because there one needs to set width and height attributes for a ShapeDrawable using the size tag.

I suppose Android needs the size to figure out how to scale the drawable (-> aspect ratio!) while taking into account the insets (top, left, right, bottom).

And as is sometimes the case with malformed (for a specific API level) xml, Android failed silently and simply did not draw the shape.

So the solution is:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:width="80px" android:height="80px"
        android:top="0px" android:left="0px" 
        android:right="0px" android:bottom="0px">
        <shape android:shape="rectangle">
            <solid android:color="@color/deep_orange"/>
        </shape>
    </item>
    <item android:width="60px" android:height="60px"
        android:top="10px" android:left="10px" 
        android:right="10px" android:bottom="10px">
        <shape android:shape="oval">
            <solid android:color="@color/light_yellow"/>
            <size android:height="60px" android:width="60px"/>
        </shape>
    </item>
</layer-list>
Pantomime answered 9/9, 2016 at 13:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.