Skip to content

Instantly share code, notes, and snippets.

@DarkionAvey
Last active April 28, 2023 12:26
Show Gist options
  • Select an option

  • Save DarkionAvey/71cc8d31b5f4447abe598753e63e1664 to your computer and use it in GitHub Desktop.

Select an option

Save DarkionAvey/71cc8d31b5f4447abe598753e63e1664 to your computer and use it in GitHub Desktop.
iOS-like spinner as an animated vector drawable for Android without the need of custom classes, or worse, gifs. Use support library to get it to work on older devices. To change color, simply change fillColor but not the alpha. You have to register a callback to make it repeat, because android doesn't allow animationset to repeat
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:name="vector"
android:width="20dp"
android:height="20dp"
android:viewportWidth="60"
android:viewportHeight="60">
<path
android:name="path_1"
android:fillAlpha="0.2"
android:fillColor="#000000"
android:pathData="M 33 12 C 33 13.7 31.7 15 30 15 C 28.3 15 27 13.7 27 12 L 27 3 C 27 1.3 28.3 0 30 0 C 31.7 0 33 1.3 33 3 L 33 12 Z M 33 48 C 33 46.3 31.7 45 30 45 C 28.3 45 27 46.3 27 48 L 27 57 C 27 58.7 28.3 60 30 60 C 31.7 60 33 58.7 33 57 L 33 48 Z M 3 27 C 1.3 27 0 28.3 0 30 C 0 31.7 1.3 33 3 33 L 12 33 C 13.7 33 15 31.7 15 30 C 15 28.3 13.7 27 12 27 L 3 27 Z M 48 27 C 46.3 27 45 28.3 45 30 C 45 31.7 46.3 33 48 33 L 57 33 C 58.7 33 60 31.7 60 30 C 60 28.3 58.7 27 57 27 L 48 27 Z M 5.1 40.9 C 3.7 41.8 3.2 43.6 4 45 C 4.8 46.4 6.7 46.9 8.1 46.1 L 15.9 41.6 C 17.3 40.8 17.8 38.9 17 37.5 C 16.2 36.1 14.3 35.6 12.9 36.4 L 5.1 40.9 Z M 44.1 18.4 C 42.7 19.2 42.2 21.1 43 22.5 C 43.8 23.9 45.7 24.4 47.1 23.6 L 54.9 19.1 C 56.3 18.3 56.8 16.4 56 15 C 55.2 13.6 53.3 13.1 51.9 13.9 L 44.1 18.4 Z M 40.9 54.9 C 41.7 56.3 43.6 56.8 45 56 C 46.4 55.2 46.9 53.3 46.1 51.9 L 41.6 44.1 C 40.8 42.7 38.9 42.2 37.5 43 C 36.1 43.8 35.6 45.7 36.4 47.1 L 40.9 54.9 Z M 18.4 15.9 C 19.2 17.3 21.1 17.8 22.5 17 C 23.9 16.2 24.4 14.3 23.6 12.9 L 19.1 5.1 C 18.3 3.7 16.4 3.2 15 4 C 13.6 4.8 13.1 6.7 13.9 8.1 L 18.4 15.9 Z M 13.9 51.9 C 13.1 53.3 13.6 55.2 15 56 C 16.4 56.8 18.3 56.3 19.1 54.9 L 23.6 47.1 C 24.4 45.7 23.9 43.8 22.5 43 C 21.1 42.2 19.2 42.7 18.4 44.1 L 13.9 51.9 Z M 36.4 12.9 C 35.6 14.3 36.1 16.2 37.5 17 C 38.9 17.8 40.8 17.3 41.6 15.9 L 46.1 8.1 C 46.9 6.7 46.4 4.8 45 4 C 43.6 3.2 41.7 3.7 40.9 5.1 L 36.4 12.9 Z M 51.9 46.1 C 53.3 46.9 55.2 46.4 56 45 C 56.8 43.6 56.3 41.7 54.9 40.9 L 47.1 36.4 C 45.7 35.6 43.8 36.1 43 37.5 C 42.2 38.9 42.7 40.8 44.1 41.6 L 51.9 46.1 Z M 12.9 23.6 C 14.3 24.4 16.2 23.9 17 22.5 C 17.8 21.1 17.3 19.2 15.9 18.4 L 8.1 13.9 C 6.7 13.1 4.8 13.6 4 15 C 3.2 16.4 3.7 18.3 5.1 19.1 L 12.9 23.6 Z" />
<group
android:name="group"
android:pivotX="30"
android:pivotY="30">
<path
android:name="path_2"
android:fillAlpha="0.2"
android:fillColor="#000000"
android:pathData="M 56 15 C 55.5 14 54.4 13.5 53.4 13.5 C 52.9 13.5 52.4 13.6 51.9 13.9 L 44.1 18.4 C 42.7 19.2 42.2 21.1 43 22.5 C 43.6 23.5 44.6 24 45.6 24 C 46.1 24 46.6 23.9 47.1 23.6 L 54.9 19.1 C 56.3 18.3 56.8 16.4 56 15 Z" />
<path
android:name="path_3"
android:fillAlpha="0.4"
android:fillColor="#000000"
android:pathData="M 59.1 27.9 C 58.6 27.3 57.9 27 57 27 L 48 27 C 46.3 27 45 28.3 45 30 C 45 30.8 45.3 31.6 45.9 32.1 C 46.4 32.6 47.2 33 48 33 L 57 33 C 58.7 33 60 31.7 60 30 C 60 29.2 59.7 28.4 59.1 27.9 Z" />
<path
android:name="path_4"
android:fillAlpha="0.6"
android:fillColor="#000000"
android:pathData="M 54.9 40.9 L 47.1 36.4 C 45.7 35.6 43.8 36.1 43 37.5 C 42.7 38 42.6 38.5 42.6 39 C 42.6 40 43.1 41 44.1 41.6 L 51.9 46.1 C 53.3 46.9 55.2 46.4 56 45 C 56.3 44.5 56.4 44 56.4 43.5 C 56.4 42.5 55.9 41.5 54.9 40.9 Z" />
<path
android:name="path_5"
android:fillAlpha="0.8"
android:fillColor="#000000"
android:pathData="M 46.1 51.9 L 41.6 44.1 C 40.8 42.7 38.9 42.2 37.5 43 C 36.5 43.6 36 44.6 36 45.6 C 36 46.1 36.1 46.6 36.4 47.1 L 40.9 54.9 C 41.7 56.3 43.6 56.8 45 56 C 46 55.4 46.5 54.4 46.5 53.4 C 46.5 52.9 46.4 52.4 46.1 51.9 Z" />
<path
android:name="path_6"
android:fillColor="#000000"
android:pathData="M 30 45 C 29.2 45 28.4 45.3 27.9 45.9 C 27.4 46.4 27 47.2 27 48 L 27 57 C 27 58.7 28.3 60 30 60 C 30.8 60 31.6 59.7 32.1 59.1 C 32.6 58.6 33 57.8 33 57 L 33 48 C 33 46.3 31.7 45 30 45 Z" />
</group>
</vector>
</aapt:attr>
<target android:name="group">
<aapt:attr name="android:animation">
<set android:ordering="sequentially">
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="0"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="30"
android:valueType="floatType" />
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="30"
android:valueTo="30"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="30"
android:valueTo="60"
android:valueType="floatType" />
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="60"
android:valueTo="60"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="60"
android:valueTo="90"
android:valueType="floatType" />
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="90"
android:valueTo="90"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="90"
android:valueTo="120"
android:valueType="floatType" />
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="120"
android:valueTo="120"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="120"
android:valueTo="150"
android:valueType="floatType" />
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="150"
android:valueTo="150"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="150"
android:valueTo="180"
android:valueType="floatType" />
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="180"
android:valueTo="180"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="180"
android:valueTo="210"
android:valueType="floatType" />
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="210"
android:valueTo="210"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="210"
android:valueTo="240"
android:valueType="floatType" />
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="240"
android:valueTo="240"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="240"
android:valueTo="270"
android:valueType="floatType" />
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="270"
android:valueTo="270"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="270"
android:valueTo="300"
android:valueType="floatType" />
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="300"
android:valueTo="300"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="300"
android:valueTo="330"
android:valueType="floatType" />
<objectAnimator
android:duration="100"
android:propertyName="rotation"
android:valueFrom="330"
android:valueTo="330"
android:valueType="floatType" />
<objectAnimator
android:duration="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="rotation"
android:valueFrom="330"
android:valueTo="360"
android:valueType="floatType" />
</set>
</aapt:attr>
</target>
</animated-vector>
{
"version": 1,
"layers": {
"vectorLayer": {
"id": "560",
"name": "vector",
"type": "vector",
"width": 60,
"height": 60,
"children": [
{
"id": "428",
"name": "path_1",
"type": "path",
"pathData": "M 33 12 C 33 13.7 31.7 15 30 15 C 28.3 15 27 13.7 27 12 L 27 3 C 27 1.3 28.3 0 30 0 C 31.7 0 33 1.3 33 3 L 33 12 Z M 33 48 C 33 46.3 31.7 45 30 45 C 28.3 45 27 46.3 27 48 L 27 57 C 27 58.7 28.3 60 30 60 C 31.7 60 33 58.7 33 57 L 33 48 Z M 3 27 C 1.3 27 0 28.3 0 30 C 0 31.7 1.3 33 3 33 L 12 33 C 13.7 33 15 31.7 15 30 C 15 28.3 13.7 27 12 27 L 3 27 Z M 48 27 C 46.3 27 45 28.3 45 30 C 45 31.7 46.3 33 48 33 L 57 33 C 58.7 33 60 31.7 60 30 C 60 28.3 58.7 27 57 27 L 48 27 Z M 5.1 40.9 C 3.7 41.8 3.2 43.6 4 45 C 4.8 46.4 6.7 46.9 8.1 46.1 L 15.9 41.6 C 17.3 40.8 17.8 38.9 17 37.5 C 16.2 36.1 14.3 35.6 12.9 36.4 L 5.1 40.9 Z M 44.1 18.4 C 42.7 19.2 42.2 21.1 43 22.5 C 43.8 23.9 45.7 24.4 47.1 23.6 L 54.9 19.1 C 56.3 18.3 56.8 16.4 56 15 C 55.2 13.6 53.3 13.1 51.9 13.9 L 44.1 18.4 Z M 40.9 54.9 C 41.7 56.3 43.6 56.8 45 56 C 46.4 55.2 46.9 53.3 46.1 51.9 L 41.6 44.1 C 40.8 42.7 38.9 42.2 37.5 43 C 36.1 43.8 35.6 45.7 36.4 47.1 L 40.9 54.9 Z M 18.4 15.9 C 19.2 17.3 21.1 17.8 22.5 17 C 23.9 16.2 24.4 14.3 23.6 12.9 L 19.1 5.1 C 18.3 3.7 16.4 3.2 15 4 C 13.6 4.8 13.1 6.7 13.9 8.1 L 18.4 15.9 Z M 13.9 51.9 C 13.1 53.3 13.6 55.2 15 56 C 16.4 56.8 18.3 56.3 19.1 54.9 L 23.6 47.1 C 24.4 45.7 23.9 43.8 22.5 43 C 21.1 42.2 19.2 42.7 18.4 44.1 L 13.9 51.9 Z M 36.4 12.9 C 35.6 14.3 36.1 16.2 37.5 17 C 38.9 17.8 40.8 17.3 41.6 15.9 L 46.1 8.1 C 46.9 6.7 46.4 4.8 45 4 C 43.6 3.2 41.7 3.7 40.9 5.1 L 36.4 12.9 Z M 51.9 46.1 C 53.3 46.9 55.2 46.4 56 45 C 56.8 43.6 56.3 41.7 54.9 40.9 L 47.1 36.4 C 45.7 35.6 43.8 36.1 43 37.5 C 42.2 38.9 42.7 40.8 44.1 41.6 L 51.9 46.1 Z M 12.9 23.6 C 14.3 24.4 16.2 23.9 17 22.5 C 17.8 21.1 17.3 19.2 15.9 18.4 L 8.1 13.9 C 6.7 13.1 4.8 13.6 4 15 C 3.2 16.4 3.7 18.3 5.1 19.1 L 12.9 23.6 Z",
"fillColor": "#231f20",
"fillAlpha": 0.2,
"strokeWidth": 1
},
{
"id": "563",
"name": "group",
"type": "group",
"pivotX": 30,
"pivotY": 30,
"children": [
{
"id": "454",
"name": "path_2",
"type": "path",
"pathData": "M 56 15 C 55.5 14 54.4 13.5 53.4 13.5 C 52.9 13.5 52.4 13.6 51.9 13.9 L 44.1 18.4 C 42.7 19.2 42.2 21.1 43 22.5 C 43.6 23.5 44.6 24 45.6 24 C 46.1 24 46.6 23.9 47.1 23.6 L 54.9 19.1 C 56.3 18.3 56.8 16.4 56 15 Z",
"fillColor": "#231f20",
"fillAlpha": 0.2,
"strokeWidth": 1
},
{
"id": "480",
"name": "path_3",
"type": "path",
"pathData": "M 59.1 27.9 C 58.6 27.3 57.9 27 57 27 L 48 27 C 46.3 27 45 28.3 45 30 C 45 30.8 45.3 31.6 45.9 32.1 C 46.4 32.6 47.2 33 48 33 L 57 33 C 58.7 33 60 31.7 60 30 C 60 29.2 59.7 28.4 59.1 27.9 Z",
"fillColor": "#231f20",
"fillAlpha": 0.4,
"strokeWidth": 1
},
{
"id": "506",
"name": "path_4",
"type": "path",
"pathData": "M 54.9 40.9 L 47.1 36.4 C 45.7 35.6 43.8 36.1 43 37.5 C 42.7 38 42.6 38.5 42.6 39 C 42.6 40 43.1 41 44.1 41.6 L 51.9 46.1 C 53.3 46.9 55.2 46.4 56 45 C 56.3 44.5 56.4 44 56.4 43.5 C 56.4 42.5 55.9 41.5 54.9 40.9 Z",
"fillColor": "#231f20",
"fillAlpha": 0.6,
"strokeWidth": 1
},
{
"id": "532",
"name": "path_5",
"type": "path",
"pathData": "M 46.1 51.9 L 41.6 44.1 C 40.8 42.7 38.9 42.2 37.5 43 C 36.5 43.6 36 44.6 36 45.6 C 36 46.1 36.1 46.6 36.4 47.1 L 40.9 54.9 C 41.7 56.3 43.6 56.8 45 56 C 46 55.4 46.5 54.4 46.5 53.4 C 46.5 52.9 46.4 52.4 46.1 51.9 Z",
"fillColor": "#231f20",
"fillAlpha": 0.8,
"strokeWidth": 1
},
{
"id": "558",
"name": "path_6",
"type": "path",
"pathData": "M 30 45 C 29.2 45 28.4 45.3 27.9 45.9 C 27.4 46.4 27 47.2 27 48 L 27 57 C 27 58.7 28.3 60 30 60 C 30.8 60 31.6 59.7 32.1 59.1 C 32.6 58.6 33 57.8 33 57 L 33 48 C 33 46.3 31.7 45 30 45 Z",
"fillColor": "#231f20",
"strokeWidth": 1
}
]
}
]
},
"hiddenLayerIds": []
},
"timeline": {
"animation": {
"id": "562",
"name": "anim",
"duration": 1201,
"blocks": [
{
"id": "565",
"layerId": "563",
"propertyName": "rotation",
"startTime": 100,
"endTime": 101,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 0,
"toValue": 30
},
{
"id": "567",
"layerId": "563",
"propertyName": "rotation",
"startTime": 200,
"endTime": 201,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 30,
"toValue": 60
},
{
"id": "568",
"layerId": "563",
"propertyName": "rotation",
"startTime": 300,
"endTime": 301,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 60,
"toValue": 90
},
{
"id": "569",
"layerId": "563",
"propertyName": "rotation",
"startTime": 400,
"endTime": 401,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 90,
"toValue": 120
},
{
"id": "570",
"layerId": "563",
"propertyName": "rotation",
"startTime": 500,
"endTime": 501,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 120,
"toValue": 150
},
{
"id": "571",
"layerId": "563",
"propertyName": "rotation",
"startTime": 600,
"endTime": 601,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 150,
"toValue": 180
},
{
"id": "572",
"layerId": "563",
"propertyName": "rotation",
"startTime": 700,
"endTime": 701,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 180,
"toValue": 210
},
{
"id": "573",
"layerId": "563",
"propertyName": "rotation",
"startTime": 800,
"endTime": 801,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 210,
"toValue": 240
},
{
"id": "575",
"layerId": "563",
"propertyName": "rotation",
"startTime": 900,
"endTime": 901,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 240,
"toValue": 270
},
{
"id": "576",
"layerId": "563",
"propertyName": "rotation",
"startTime": 1000,
"endTime": 1001,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 270,
"toValue": 300
},
{
"id": "577",
"layerId": "563",
"propertyName": "rotation",
"startTime": 1100,
"endTime": 1101,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 300,
"toValue": 330
},
{
"id": "578",
"layerId": "563",
"propertyName": "rotation",
"startTime": 1200,
"endTime": 1201,
"interpolator": "FAST_OUT_SLOW_IN",
"type": "number",
"fromValue": 330,
"toValue": 360
}
]
}
}
}
@ugommirikwe
Copy link

To change the color programmatically, you'd use the <asAnimatedVectorDrawable>.setTint(color), quite like so:

(ContextCompat.getDrawable(context, R.drawable.ic_spinner_animated) as AnimatedVectorDrawable)
  .apply {
     setTint(trueColor)
     start()
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment