Search code examples
androidrenderingdrawable

Why does the xml drawable look different in Android Studio than the phone?


I am trying to make a circle progressbar that looks like a snake. In my phone, it looks exactly like I want:

enter image description here

Yet, Android Studio shows something very different:

enter image description here

That is, the "head" of the snake is stretched, out of center... I am afraid that Android will show different drawables in different phones. How to solve this?

This is the progress_gradient.xml of the drawable that I placed in res > drawables (I came out to this after several tries and errors in my phone):

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="720">

    <layer-list>
        <item>
            <shape
                android:innerRadiusRatio="3"
                android:shape="ring"
                android:thicknessRatio="30"
                android:useLevel="false">

                <size
                    android:width="100sp"
                    android:height="100sp" />

                <gradient
                    android:angle="0"
                    android:endColor="#9ac14e"
                    android:startColor="@android:color/transparent"
                    android:type="sweep"
                    android:useLevel="false" />

            </shape>
        </item>
        <item
            android:left="82sp"
            android:right="16dp"
            android:top="47sp"
            android:bottom="45sp"
            >

            <shape
                android:shape="oval" >
                <solid android:color="#9ac14e"/>

            <size
                    android:width="1sp"
                    android:height="5sp" />

            </shape>
        </item>
    </layer-list>

</rotate>

And this is how I load it in the layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"

android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:orientation="vertical">

...

<ProgressBar
    android:id="@+id/waitcircle"
    android:layout_width="100sp"
    android:layout_height="100sp"
    android:layout_marginTop="50dp"
    android:layout_gravity="center_horizontal"
    android:indeterminate="true"
    android:indeterminateDrawable="@drawable/progress_gradient"/>

</LinearLayout>

Solution

  • It looks like the "head" is being overdrawn by the tail. The missing chunk matches the area where the tail is drawn. If the head was drawn first and the tail was drawn over it without transparency, this is what I'd expect to see.

    Android Studio and the device have different drawing systems. When they don't agree, assume you'll see the device's version. However for something like this I would test on a variety of OS versions to double check, this is the kind of thing where a tweak to the implementation of the drawable subsystem could break things for you.

    As an aside- I'm not sure I would have gone with an xml drawable for this. If you really want to control how it looks, I would have gone with either a vector drawable or a png image.

    One other possible problem in your code- you have a mix of sp and dp sizes in your "head". Those are different things. If someone with bad eyesight has the text a bit bigger, it will break you. Use one or the other. For this, it should be exclusively dp- there's no reason to scale this based on text size.