How to create this layout while fetching data ?
You could have used the Facebook shimmer library for this which is very straightforward.
Facebook Shimmer Library
But for more fine-tuned control you might have to write an animated vector like this.
Source for code Snippet
<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="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<clip-path
android:name="heart"
android:pathData="M 7 3 C 5.465 3 3.922 3.5 2.75 4.7 C 0.407 7.1 0.471 10.8 2.75 13.2 L 12 23 L 21.25 13.2 C 23.529 10.8 23.593 7.1 21.25 4.7 C 18.907 2.4 15.093 2.4 12.75 4.7 L 12 5.5 L 11.25 4.7 C 10.078 3.5 8.536 3 7 3 Z"/>
<path
android:name="path"
android:pathData="M 7 3 C 5.465 3 3.922 3.5 2.75 4.7 C 0.407 7.1 0.471 10.8 2.75 13.2 L 12 23 L 21.25 13.2 C 23.529 10.8 23.593 7.1 21.25 4.7 C 18.907 2.4 15.093 2.4 12.75 4.7 L 12 5.5 L 11.25 4.7 C 10.078 3.5 8.536 3 7 3 Z"
android:fillColor="#ff0000"/>
<group android:name="group">
<path
android:name="shimmer"
android:pathData="M 4 0 L 24 19 L 22 22 L 0 3 Z">
<aapt:attr name="android:fillColor">
<gradient
android:endColor="#FFC500"
android:endX="24"
android:endY="24"
android:startColor="#ED613A"
android:startX="0"
android:startY="0"
android:type="linear" />
</aapt:attr>
</path>
</group>
</vector>
</aapt:attr>
<target android:name="group">
<aapt:attr name="android:animation">
<set>
<objectAnimator
android:propertyName="translateX"
android:duration="700"
android:valueFrom="10"
android:valueTo="-10"
android:valueType="floatType"
android:interpolator="#android:anim/linear_interpolator"/>
<objectAnimator
android:propertyName="translateY"
android:duration="700"
android:valueFrom="-10"
android:valueTo="10"
android:valueType="floatType"
android:interpolator="#android:anim/linear_interpolator"/>
</set>
</aapt:attr>
</target>
</animated-vector>
I've used ShapeShifter to create an animation vector drawable which perform some trim path and some path data change.
Here's the result:
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:name="omino"
android:pathData="M 9 10 C 7 10 7 10 7 8 C 7 6 7 6 9 6 C 11 6 11 6 11 8 C 11 10 11 10 9 10 L 9 16"
android:strokeColor="#000000"
android:strokeAlpha="0.7"
android:strokeWidth="0.3"
android:strokeLineCap="round"
android:strokeLineJoin="round"/>
<path
android:name="bilancia"
android:pathData="M 3 16 L 20 16 M 12 16 L 12 14 L 22 14"
android:strokeColor="#000000"
android:strokeAlpha="0.7"
android:strokeWidth="0.3"
android:strokeLineCap="round"
android:strokeLineJoin="round"/>
<path
android:name="abox"
android:pathData="M 13 14 L 13 12 L 19 12 L 19 14 L 13 14"
android:strokeColor="#000000"
android:strokeAlpha="0.7"
android:strokeWidth="0.3"
android:strokeLineCap="round"
android:strokeLineJoin="round"/>
<path
android:name="braccia"
android:pathData="M 14 14 L 9 11 L 13 12.5"
android:strokeColor="#000000"
android:strokeAlpha="0.7"
android:strokeWidth="0.3"
android:strokeLineCap="round"
android:strokeLineJoin="round"/>
</vector>
</aapt:attr>
<target android:name="omino">
<aapt:attr name="android:animation">
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="trimPathEnd"
android:duration="1000"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="#android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="bilancia">
<aapt:attr name="android:animation">
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="trimPathStart"
android:duration="1000"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
android:interpolator="#android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="abox">
<aapt:attr name="android:animation">
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="trimPathEnd"
android:duration="1000"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:interpolator="#android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="pathData"
android:startOffset="2000"
android:duration="1000"
android:valueFrom="M 13 12 L 13 10 L 19 10 L 19 12 L 13 12"
android:valueTo="M 13 14 L 13 12 L 19 12 L 19 14 L 13 14"
android:valueType="pathType"
android:interpolator="#android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="pathData"
android:startOffset="500"
android:duration="1000"
android:valueFrom="M 13 14 L 13 12 L 19 12 L 19 14 L 13 14"
android:valueTo="M 13 12 L 13 10 L 19 10 L 19 12 L 13 12"
android:valueType="pathType"
android:interpolator="#android:interpolator/fast_out_slow_in"/>
</set>
</aapt:attr>
</target>
<target android:name="braccia">
<aapt:attr name="android:animation">
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="trimPathStart"
android:duration="1000"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
android:interpolator="#android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="pathData"
android:startOffset="500"
android:duration="1000"
android:valueFrom="M 14 14 L 9 11 L 13 12.5"
android:valueTo="M 14 12 L 9 11 L 13 10.5"
android:valueType="pathType"
android:interpolator="#android:interpolator/fast_out_slow_in"/>
<objectAnimator
android:propertyName="pathData"
android:startOffset="2000"
android:duration="1000"
android:valueFrom="M 14 12 L 9 11 L 13 10.5"
android:valueTo="M 14 14 L 9 11 L 13 12.5"
android:valueType="pathType"
android:interpolator="#android:interpolator/fast_out_slow_in"/>
</set>
</aapt:attr>
</target>
Android studio keeps enlighting animated-vector and target as errors. But in compilation all works fine.
I imported this file as a drawable inside my project. Then in the layout I added an ImageView without any src.
With this code I set the animated vector drawable to the imageview and i start the animation:
AnimazioneVettore = (ImageView)view.findViewById(R.id.ImgVectorAnim);
animatedVector = AnimatedVectorDrawableCompat.create(getContext(), R.drawable.no_abox_animated);
AnimazioneVettore.setImageDrawable(animatedVector);
animatedVector.start();
no_abox_animated is the vector file.
When I start the app no error is fired, the vector is loaded inside the imageview and the animation starts.
The first animation "Trim path end/start". It works fine except for "bilancia". Here the animation perform an orrible "jump" insted of animate the last 2 Lines.
At 500 ms the path animation should start. but nothing happens.
At 200 the last path animiation should start but it does not work either.
I'm using 'com.android.support:appcompat-v7:25.3.1'
First the easy part. Path morphing for AnimatedVectorDrawables was only added to the support library in version 25.4.0 (release notes). So for your pathData animations where nothing is happening you just need to updated the support library version you are using.
As for your "bilancia" problem, this is an issue to do with the way AnimatedVectorDrawables handle trimPath when there is more than one moveTo command (M). You can find an issue filed here. Basically your path is drawing two lines and when combining this with trimPath it doesn't work very well. I'd suggest splitting the two lines in "bilancia" into two separate paths and animating those instead.
I have a following vector drawable:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25dp"
android:height="25dp"
android:viewportWidth="25"
android:viewportHeight="25">
<path
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeWidth="1"
android:pathData="M12.5,25 C19.4035594,25 25,19.4035594 25,12.5 C25,5.59644063 19.4035594,0 12.5,0
C5.59644063,0 0,5.59644063 0,12.5 C0,19.4035594 5.59644063,25 12.5,25 Z M12.5,24
C18.8512746,24 24,18.8512746 24,12.5 C24,6.14872538 18.8512746,1 12.5,1
C6.14872538,1 1,6.14872538 1,12.5 C1,18.8512746 6.14872538,24 12.5,24 Z M16,6
C17.6568542,6 19,7.34226429 19,8.99878564 L19,16.0012144 C19,17.6573979
17.6534829,19 16,19 C14.3431458,19 13,17.6577357 13,16.0012144 L13,8.99878564
C13,7.34260206 14.3465171,6 16,6 Z M14,16.0012144 C14,17.1052262 14.8952058,18
16,18 C17.1026267,18 18,17.1036857 18,16.0012144 L18,8.99878564 C18,7.89477378
17.1047942,7 16,7 C14.8973733,7 14,7.89631432 14,8.99878564 L14,16.0012144 Z
M8.33473905,12.5 C8.14415114,12.3451212 7.57820716,11.8273213
7.57820716,11.8273213 C6.80306599,11.0695455 6,10.0347728 6,9 C6,7 7,6 9,6 C11,6
12,7 12,9 C12,10.0347728 11.196934,11.0695455 10.4217928,11.8273213
C10.4217928,11.8273213 9.85584886,12.3451212 9.66526095,12.5
C9.85584886,12.6548788 10.4217928,13.1726787 10.4217928,13.1726787
C11.196934,13.9304545 12,14.9652272 12,16 C12,18 11,19 9,19 C7,19 6,18 6,16
C6,14.9652272 6.80306599,13.9304545 7.57820716,13.1726787 C7.57820716,13.1726787
8.14415114,12.6548788 8.33473905,12.5 Z M9.03460423,12 C10.1996214,11.0532638
11,9.74316 11,9 C11,7.55228475 10.4477153,7 9,7 C7.55228475,7 7,7.55228475 7,9
C7,9.74316 7.86958707,11.0532638 9.03460423,12 L8.96539577,13
C7.80037862,13.9467362 7,15.25684 7,16 C7,17.4477153 7.55228475,18 9,18
C10.4477153,18 11,17.4477153 11,16 C11,15.25684 10.1304129,13.9467362
8.96539577,13 L9.03460423,12 Z" />
</vector>
On preview tab in Android Studio it looks like this (and this is what is needed):
but when I set it programmatically to ImageView as its source, with the code:
imageMenuItem.setImageResource(R.drawable.keno);
it looks like this:
The xml code for ImageView is simple:
<ImageView
android:id="#+id/image_menu_item"
style="#style/UpperItemsImageLeftMenu"
app:srcCompat="#drawable/leftmenu_keno"
android:layout_width="#dimen/upper_item_image_dim_left_menu"
android:layout_height="#dimen/upper_item_image_dim_left_menu"
/>
The dark grey is the background, set elsewhere. Does anyone know how I can fix this?
Ok, so here is the solution.
Source of the problem
Problem is with this fill-rule in xml: android:fillType="evenOdd". Android doesn't support this parameter until Nougat version, so we must somehow avoid it. As #LewisMcGeary pointed out, there is an excellent explanation on this topis on : Marc Allison's blog. More about this fill-rule can be found on this link as suggested by #Duopixel.
My solution
I solved this problem by changing the software. I used this online tool as suggested by before mentioned blog post with following settings:
and then I saved it to xml with following content:
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:auto="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
tools:ignore="NewApi"
android:viewportWidth="25"
auto:viewportWidth="25"
android:viewportHeight="25"
auto:viewportHeight="25"
android:width="25dp"
auto:width="25dp"
android:height="25dp"
auto:height="25dp">
<path
android:pathData="M12.5 25C19.40356 25 25 19.40356 25 12.5C25 5.596441 19.40356 0 12.5 0C5.596441 0 0 5.596441 0 12.5C0 19.40356 5.596441 25 12.5 25M16 6C17.65685 6 19 7.342264 19 8.998786L19 16. 00121C19 17.6574 17.65348 19 16 19C14.34315 19 13 17.65774 13 16.00121L13 8.998786C13 7.342602 14.34652 6 16 6M14 16.00121C14 17.10523 14.89521 18 16 18C17.10263 18 18 17.10369 18 16.00121L18 8. 998786C18 7.894774 17.10479 7 16 7C14.89737 7 14 7.896314 14 8.998786L14 16.00121M8.334739 12.5C8.144151 12.34512 7.578207 11.82732 7.578207 11.82732C6.803066 11.06955 6 10.03477 6 9C6 7 7 6 9 6C11 6 12 7 12 9C12 10.03477 11.19693 11.06955 10.42179 11.82732C10.42179 11.82732 9.855849 12.34512 9.665261 12.5C9.855849 12.65488 10.42179 13.17268 10.42179 13.17268C11.19693 13.93046 12 14.96523 12 16C12 18 11 19 9 19C7 19 6 18 6 16C6 14.96523 6.803066 13.93046 7.578207 13.17268C7.578207 13.17268 8.144151 12.65488 8.334739 12.5M9.034604 12C10.19962 11.05326 11 9.74316 11 9C11 7.552285 10.44771 7 9 7C7.552285 7 7 7.552285 7 9C7 9.74316 7.869587 11.05326 9.034604 12M8.965396 13C7.800378 13.94674 7 15.25684 7 16C7 17.44772 7.552285 18 9 18C10.44771 18 11 17.44772 11 16C11 15.25684 10.13041 13 .94674 8.965396 13M12.5 24C6.148726 24 1 18.85127 1 12.5C1 6.148726 6.148726 1 12.5 1C18.85127 1 24 6.148726 24 12.5C24 18.85127 18.85127 24 12.5 24"
auto:pathData="M12.5 25C19.40356 25 25 19.40356 25 12.5C25 5.596441 19.40356 0 12.5 0C5.596441 0 0 5.596441 0 12.5C0 19.40356 5.596441 25 12.5 25M16 6C17.65685 6 19 7.342264 19 8.998786L19 16. 00121C19 17.6574 17.65348 19 16 19C14.34315 19 13 17.65774 13 16.00121L13 8.998786C13 7.342602 14.34652 6 16 6M14 16.00121C14 17.10523 14.89521 18 16 18C17.10263 18 18 17.10369 18 16.00121L18 8. 998786C18 7.894774 17.10479 7 16 7C14.89737 7 14 7.896314 14 8.998786L14 16.00121M8.334739 12.5C8.144151 12.34512 7.578207 11.82732 7.578207 11.82732C6.803066 11.06955 6 10.03477 6 9C6 7 7 6 9 6C11 6 12 7 12 9C12 10.03477 11.19693 11.06955 10.42179 11.82732C10.42179 11.82732 9.855849 12.34512 9.665261 12.5C9.855849 12.65488 10.42179 13.17268 10.42179 13.17268C11.19693 13.93046 12 14.96523 12 16C12 18 11 19 9 19C7 19 6 18 6 16C6 14.96523 6.803066 13.93046 7.578207 13.17268C7.578207 13.17268 8.144151 12.65488 8.334739 12.5M9.034604 12C10.19962 11.05326 11 9.74316 11 9C11 7.552285 10.44771 7 9 7C7.552285 7 7 7.552285 7 9C7 9.74316 7.869587 11.05326 9.034604 12M8.965396 13C7.800378 13.94674 7 15.25684 7 16C7 17.44772 7.552285 18 9 18C10.44771 18 11 17.44772 11 16C11 15.25684 10.13041 13 .94674 8.965396 13M12.5 24C6.148726 24 1 18.85127 1 12.5C1 6.148726 6.148726 1 12.5 1C18.85127 1 24 6.148726 24 12.5C24 18.85127 18.85127 24 12.5 24"
android:fillColor="#ffffff"
auto:fillColor="#ffffff" />
</vector>
I manually removed all auto:xxx tags and ended up with
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="NewApi"
android:viewportWidth="25"
android:viewportHeight="25"
android:width="25dp"
android:height="25dp"
>
<path
android:pathData="M12.5 25C19.40356 25 25 19.40356 25 12.5C25 5.596441 19.40356 0 12.5 0C5.596441 0 0 5.596441 0 12.5C0 19.40356 5.596441 25 12.5 25M16 6C17.65685 6 19 7.342264 19 8.998786L19 16.00121C19 17.6574 17.65348 19 16 19C14.34315 19 13 17.65774 13 16.00121L13 8.998786C13 7.342602 14.34652 6 16 6M14 16.00121C14 17.10523 14.89521 18 16 18C17.10263 18 18 17.10369 18 16.00121L18 8.998786C18 7.894774 17.10479 7 16 7C14.89737 7 14 7.896314 14 8.998786L14 16.00121M8.334739 12.5C8.144151 12.34512 7.578207 11.82732 7.578207 11.82732C6.803066 11.06955 6 10.03477 6 9C6 7 7 6 9 6C11 6 12 7 12 9C12 10.03477 11.19693 11.06955 10.42179 11.82732C10.42179 11.82732 9.855849 12.34512 9.665261 12.5C9.855849 12.65488 10.42179 13.17268 10.42179 13.17268C11.19693 13.93046 12 14.96523 12 16C12 18 11 19 9 19C7 19 6 18 6 16C6 14.96523 6.803066 13.93046 7.578207 13.17268C7.578207 13.17268 8.144151 12.65488 8.334739 12.5M9.034604 12C10.19962 11.05326 11 9.74316 11 9C11 7.552285 10.44771 7 9 7C7.552285 7 7 7.552285 7 9C7 9.74316 7.869587 11.05326 9.034604 12M8.965396 13C7.800378 13.94674 7 15.25684 7 16C7 17.44772 7.552285 18 9 18C10.44771 18 11 17.44772 11 16C11 15.25684 10.13041 13.94674 8.965396 13M12.5 24C6.148726 24 1 18.85127 1 12.5C1 6.148726 6.148726 1 12.5 1C18.85127 1 24 6.148726 24 12.5C24 18.85127 18.85127 24 12.5 24"
android:fillColor="#ffffff"
/>
</vector>
which is what I was looking for.
What I want
I want to be able to draw a Vector Drawable from no path -> target. So for example, draw from nothing to a check mark SVG.
What I've tried
Here is my Vector drawable:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="128dp"
android:width="128dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:name="done"
android:pathData="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"
android:fillColor="#fff"
android:strokeWidth="1"
android:strokeLineCap="round"
android:strokeColor="#fff"/>
That is just a check mark SVG.
Here is my animation (Which I know is wrong.. :( ). The path data for animating from one vector drawable to another must have the same number of path directions:
<objectAnimator
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="0"
android:valueTo="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"
android:valueType="pathType"
xmlns:android="http://schemas.android.com/apk/res/android" />
And the animated vector (tying together the vector + animation)
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="#drawable/ic_done">
<target
android:animation="#animator/ic_disappear"
android:name="opacity"/>
This is wrong as I noted above. How then, do I create an object animator for a SVG to animate from no path to the path I want. This animation is similar to someone drawing the drawable.
As you say, the two paths descriptions have to have the same number of commands and coordinates. Your path is a filled shape, and you can only animate once linearly. So you can't do a two-step down-and-then-up check motion. At least not with a single path morph.
A first simple approach would just be to start from the path start point. That happens to be at the crook of the check mark. So it doesn't look to bad.
<svg width="200" height="200" viewBox="0 0 24 24">
<path d="M0 0">
<animate attributeName="d" attributeType="XML"
from="M9 16.2 L 9 16.2 l 0 0 L 9 16.2 9 16.2 l 0 0 L 9 16.2z"
to="M9 16.2 L 4.8 12 l -1.4 1.4 L 9 19 21 7 l -1.4-1.4 L 9 16.2z"
dur="1s" fill="freeze" />
</path>
</svg>
Or you could start it at the centre point of the corner:
<svg width="200" height="200" viewBox="0 0 24 24">
<path d="M0 0">
<animate attributeName="d" attributeType="XML"
from="M9 17.6 L 9 17.6 l 0 0 L 9 17.6 9 17.6 l 0 0 L 9 17.6z"
to="M9 16.2 L 4.8 12 l -1.4 1.4 L 9 19 21 7 l -1.4-1.4 L 9 16.2z"
dur="1s" fill="freeze" />
</path>
</svg>
Or maybe start with the corner diamond and grow the two "arms" from there.
<svg width="200" height="200" viewBox="0 0 24 24">
<path d="M0 0">
<animate attributeName="d" attributeType="XML"
from="M9 16.2 L 9 16.2 l -1.4 1.4 L 9 19 l 1.4 -1.4 l -1.4-1.4 L 9 16.2z"
to= "M9 16.2 L 4.8 12 l -1.4 1.4 L 9 19 L 21 7 l -1.4-1.4 L 9 16.2z"
dur="1s" fill="freeze" />
</path>
</svg>
You may animate trimPathEnd property from 0 to 1 in duration of your choice instead of animating pathData. So change the propertyName to trimPathEnd and changing the AnimatedVectorDrawable file also suitably. The result is as if the tick is being written now.
Further, if you want a demo read the tutorial "An Introduction to Icon Animation Techniques". There are some interactive demo items in the body of the article.
You may also read about AnimatedVectorDrawable class in android developer site. Though trimPathEnd propertyName is not in the list, it works.