Razem z pojawieniem się Material Design, Androida Lollipop wprowadzono nowy sposób przechowywania ikon. Zamiast plików graficznych jak np png postawiono na zgodny z ideą flat design plik typu svg. Nietrudno zrozumieć taką decyzję:
xxxhdpi to rozmiar dla fullHd, ileż jeszcze można tych x dodać, żeby obsługiwać 4k, albo w przyszłości 16k? 😉 Svg ma ten plus, że skaluje się bez utraty jakości, tzn jest jeden plik, który obsłuży wszystkie rozdzielczości. Dla bardziej zainteresowanych standardem, który opracował W3C zresztą link.
Aplikacji które korzystały by jednak z tego typu rozwiązań jakoś błyskawicznie nie przybywa (png znajdujący się w folderze xxxhdpi przeskaluje się na ekranie 4k, a że smartfony mają rozmiar jakieś 6-7 cali te większe, tablety jakieś 10 cali, to i tak tego gołym okiem nie widać. Może na telewizorze 4k to widać, jak się patrzy z bliska, ale nie po to są telewizory, żeby patrzeć z bliska ;). Dlatego też pliki png mają się dobrze. Zaletą stosowania svg jest możliwość korzystania z morphingu, który na png musielibyśmy wywołać jakimś zewnętrznym programem, przerabiając go zresztą na gifa. No i tak ten gif by się potem skalował na większy ekran.. Ok, wiemy już, że powinniśmy korzystać z svg. Samo korzystanie jest takie samo jak z png w Androidzie, wrzucamy plik tylko do jednego folderu: drawable, a widać go wszędzie. A teraz zabierzmy się za morphing, ufff trochę czasu mi zajęło rozgryzienie tego.
Aby móc użyć animacji morphingu na androidzie poniżej wersji 5.0 skorzystałem z biblioteki vector-compat, która dostarczyła kilka gotowych animacji:
final Animatable icon = (Animatable) ResourcesCompat.getDrawable
(getApplicationContext(), R.drawable.ic_line_to_done);
fab.setImageDrawable((Drawable)icon);
icon.start();
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_line_vector">
<target
android:name="rotationGroup"
android:animation="@anim/line_to_done_rotation" />
<target
android:name="v"
android:animation="@anim/line_to_done_path" />
</animated-vector>
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@integer/anim_duration"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"/>
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:duration="@integer/anim_duration"
android:propertyName="pathData"
android:valueFrom="@string/path_line"
android:valueTo="@string/path_done"
android:valueType="pathType"
app:vc_valueType="pathType"/>
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:width="48dp"
android:height="48dp"
android:viewportHeight="24"
android:viewportWidth="24"
app:vc_viewportHeight="24"
app:vc_viewportWidth="24">
<group
android:name="rotationGroup"
android:pivotX="12.0"
android:pivotY="12.0"
android:rotation="360.0">
<path
android:name="v"
android:fillColor="#FFFFFF"
android:pathData="@string/path_line"
app:vc_fillColor="#FFFFFF"
app:vc_pathData="@string/path_line" />
</group>
</vector>
Finalnie uzyskałem takie efekty.



