استفاده از کلاس VectorDrawable در اندروید

استفاده از کلاس VectorDrawable در اندروید
اندروید به صورت مستقیم از SVG یا Scalable Vector Graphics پشتیبانی نمیکند، اما در Lollipop یک کلاس جدید به اسم VectorDrawable معرفی کرده است و طراحان از این طریق میتوانند شکل هایی را از طریق کد بکشند، در این مقاله یاد میگیرید که چگونه با فایل XML یک VectorDrawable بسازید و به آن انیمیشن بدهید، این عملیات فقط در دستگاه هایی که اندروید 5 و بالاتر از آن دارند قابل انجام است و برای ورژن های پایین تر ساپورت مناسبی وجود ندارد، اما این تکنیک های پیشرفته را یاد بگیرید تا در آینده بتوانید به خوبی از آن استفاده کنید.
خرید شارژ ایرانسل
خرید شارژ ایرانسل، همراه اول، رایتل | خرید بسته های اینترنت ایرانسل | etore.ir
خرید سرور مجازی
ارائه سرور مجازی SSD NVMe برای اولین بار در ایران ؛ نهایت سرعت را تجربه کنید.
خرید شارژ ایرانسل
خرید شارژ ایرانسل، همراه اول، رایتل | خرید بسته های اینترنت ایرانسل | etore.ir
خودتان را اینجا معرفی کنید

1. ساخت یک Vector Drawable

وجه اشتراک بین یک VectorDrawable و یک استاندارد SVG این است که هردو از مقادیر Path برای ساخته شدن استفاده میکنند، در این مقاله، باید بدانید تگ Path جایی است که در آن نقاشی رخ میدهد، نگاهی به SVG ای میندازیم که باعث به وجود آمدن عکس زیر میشود :
فایل زیر 5 قسمت دارد :
یک مربع برای هسته ی CPU که از 2 کمان تشکیل شده.
چهار گروه که هرکدام 5 خط دارند و برای نشان دادن سیم های CPU هستند.
کد زیر عکس بالا را به صورت SVG به ما نمایش میدهد :
<?xml version="1.0" encoding="utf-8"?>
 
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path id="cpu" d="
    M341.087,157.478c7.417,0,13.435,6.018,13.435,13.435v170.174 c0,7.417-6.018,13.435-13.435,13.435H170.913 c-7.417,0-13.435-6.018-13.435-13.435V170.913 c0-7.417,6.018-13.435,13.435-13.435H341.087z
    M390.348,157.478 c0-19.785-16.041-35.826-35.826-35.826H157.479c-19.785,0-35.826,16.041-35.826,35.826v197.043 c0,19.785,16.041,35.826,35.826,35.826h197.043c19.785 0,35.826-16.041,35.826-35.826V157.478z
 
    M193.304,408.261V462h-17.913 v-53.739H193.304z
    M264.957,408.261V462h-17.914v-53.739H264.957z
    M300.783,408.261V462h-17.914v-53.739H300.783z
    M229.13,408.261 V462h-17.913v-53.739H229.13z
    M336.609,408.261V462h-17.914v-53.739H336.609z
 
    M193.304,50v53.739h-17.913V50H193.304z
    M264.957,50 v53.739h-17.914V50H264.957z
    M300.783,50v53.739h-17.914V50H300.783z
    M229.13,50v53.739h-17.913V50H229.13z
    M336.609,50v53.739 h-17.914V50H336.609z
 
    M408.261,318.695H462v17.914h-53.739V318.695z
    M408.261,247.043H462v17.914h-53.739V247.043z
    M408.261,211.217 H462v17.913h-53.739V211.217z
    M408.261,282.869H462v17.914h-53.739V282.869z
    M408.261,175.391H462v17.913h-53.739V175.391z
 
    M50,318.695h53.739v17.914H50V318.695z
    M50,247.043h53.739v17.914H50V247.043z
    M50,211.217h53.739v17.913H50V211.217z
    M50,282.869 h53.739v17.914H50V282.869z
    M50,175.391h53.739v17.913H50V175.391z" />
</svg>
کد بالا ممکن است ابتدا کمی گیج کننده به نظر بیاید، اما نیازی نیست آن را به صورت کامل بفهمید هرچند برای وضوح بیشتر هر 5 قطعه کد را در یک بلاک قرار دادیم تا بهتر قابل تشخیص باشند. قسمت بالایی شامل دو کمان است که یک مربع گرد را میکشد و قسمت های پایینی شامل شکل های بالا و پایین و راست و چپ مربع هستند، برای اینکه این کد SVG را به VectorDrawable تبدیل کنیم ابتدا نیاز داریم که شی vector را در XML خود تعریف کنیم، کد زیر از فایل vector_drawable_cpu.xml گرفته شده است :
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600" >
     
</vector>
سپس میتوانید Path را اضافه کنید، در زیر 5 تگ Path کوچکتر داریم بجای اینکه یک تگ Path بزرگ داشته باشیم :
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600" >
 
        <path
            android:name="cpu"
            android:fillColor="#000000"
            android:pathData="
                M341.087,157.478 c7.417,0,13.435,6.018,13.435,13.435 v170.174c0,7.417-6.018,13.435-13.435,13.435 H170.913 c-7.417,0-13.435-6.018-13.435-13.435V170.913c0-7.417,6.018-13.435,13.435-13.435H341.087z
                M390.348,157.478 c0-19.785-16.041-35.826-35.826-35.826H157.479c-19.785,0-35.826,16.041-35.826,35.826v197.043 c0,19.785,16.041,35.826,35.826,35.826h197.043c19.785,0,35.826-16.041,35.826-35.826V157.478z"
        />
 
        <path
            android:name="wires_bottom"
            android:fillColor="#000000"
            android:pathData="
                M193.304,408.261V462h-17.913 v-53.739H193.304z
                M264.957,408.261V462h-17.914v-53.739H264.957z
                M300.783,408.261V462h-17.914v-53.739H300.783z
                M229.13,408.261 V462h-17.913v-53.739H229.13z
                M336.609,408.261V462h-17.914v-53.739H336.609z"
        />
 
        <path
            android:name="wires_top"
            android:fillColor="#000000"
            android:pathData="
                M193.304,50v53.739h-17.913V50H193.304z
                M264.957,50 v53.739h-17.914V50H264.957z
                M300.783,50v53.739h-17.914V50H300.783z
                M229.13,50v53.739h-17.913V50H229.13z
                M336.609,50v53.739 h-17.914V50H336.609z"
        />
 
        <path
            android:name="wires_right"
            android:fillColor="#000000"
            android:pathData="
                M408.261,318.695H462v17.914h-53.739V318.695z
                M408.261,247.043H462v17.914h-53.739V247.043z
                M408.261,211.217 H462v17.913h-53.739V211.217z
                M408.261,282.869H462v17.914h-53.739V282.869z
                M408.261,175.391H462v17.913h-53.739V175.391z"
        />
         
        <path
            android:name="wires_left"
            android:fillColor="#000000"
            android:pathData="
                M50,318.695h53.739v17.914H50V318.695z
                M50,247.043h53.739v17.914H50V247.043z
                M50,211.217h53.739v17.913H50V211.217z
                M50,282.869 h53.739v17.914H50V282.869z
                M50,175.391h53.739v17.913H50V175.391z"
        />
 
</vector>
همانطور که میبینید، هر قسمت path از یک pathData استفاده میکند برای کشیدن شکل، اکنون میتوانید درون drawable فایل VectorDrawable که یک فایل XML است را وارد کنید و از آن به عنوان یک استاندارد ImageView استفاده کنید و این شکل بدون نیاز به هیچ کد Java در هر سایزی قابل تعمیم و بزرگ و کوچک شدن است.

2. دادن انیمیشن به Vector Drawable

اکنون میدانید که چگونه تنها با کد یک عکس بسازید، وقتش است که با کمی انیمیشن کار خود را زیباتر کنیم، همانگونه که در شکل زیر میبینید هرگروه از سیم ها به صورت هماهنگ باهم بزرگ و کوچک میشوند :
برای اینکه بتوانید همچین افکتی بدهید، باید هر قسمتی که میخواهیم به آن انیمیشن بدهیم را در تگ <group> قرار بدهیم، vector_drawable_cpu.xml به صورت زیر میشود :
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600" >
 
    <group
        android:name="cpu_box">
        <path
            android:name="cpu"
            android:fillColor="#000000"
            android:pathData="
            M341.087,157.478 c7.417,0,13.435,6.018,13.435,13.435 v170.174c0,7.417-6.018,13.435-13.435,13.435 H170.913 c-7.417,0-13.435-6.018-13.435-13.435V170.913c0-7.417,6.018-13.435,13.435-13.435H341.087z
            M390.348,157.478 c0-19.785-16.041-35.826-35.826-35.826H157.479c-19.785,0-35.826,16.041-35.826,35.826v197.043 c0,19.785,16.041,35.826,35.826,35.826h197.043c19.785,0,35.826-16.041,35.826-35.826V157.478z "/>
    </group>
    <group
        android:name="bottom">
        <path
            android:name="wires_bottom"
            android:fillColor="#000000"
            android:pathData="
        M193.304,408.261V462h-17.913 v-53.739H193.304z
        M264.957,408.261V462h-17.914v-53.739H264.957z
        M300.783,408.261V462h-17.914v-53.739H300.783z
        M229.13,408.261 V462h-17.913v-53.739H229.13z
        M336.609,408.261V462h-17.914v-53.739H336.609z" />
    </group>
    <group android:name="top">
        <path
            android:name="wires_top"
            android:fillColor="#000000"
            android:pathData="
        M193.304,50v53.739h-17.913V50H193.304z
        M264.957,50 v53.739h-17.914V50H264.957z
        M300.783,50v53.739h-17.914V50H300.783z
        M229.13,50v53.739h-17.913V50H229.13z
        M336.609,50v53.739 h-17.914V50H336.609z " />
    </group>
    <group android:name="right">
        <path
            android:name="wires_right"
            android:fillColor="#000000"
            android:pathData="
        M408.261,318.695H462v17.914h-53.739V318.695z
        M408.261,247.043H462v17.914h-53.739V247.043z
        M408.261,211.217 H462v17.913h-53.739V211.217z
        M408.261,282.869H462v17.914h-53.739V282.869z
        M408.261,175.391H462v17.913h-53.739V175.391z" />
    </group>
    <group android:name="left">
        <path
            android:name="wires_left"
            android:fillColor="#000000"
            android:pathData="
        M50,318.695h53.739v17.914H50V318.695z
        M50,247.043h53.739v17.914H50V247.043z
        M50,211.217h53.739v17.913H50V211.217z
        M50,282.869 h53.739v17.914H50V282.869z
        M50,175.391h53.739v17.913H50V175.391z" />
    </group>
 
</vector>
سپس، برای هر انیمیشن یک animator قرار میدهیم، در مثال زیر، یک انیمیشن برای گروه بالای سیم ها است، همچنین شما برای قسمت پایین، راست و چپ نیز به انیمیشن نیاز دارید، به مثال زیر دقت کنید :
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:propertyName="translateY"
        android:valueType="floatType"
        android:valueFrom="0"
        android:valueTo="-10"
        android:repeatMode="reverse"
        android:repeatCount="infinite"
        android:duration="250" />
</set>
همانطور که میبینید propertyName مقداری برابر با translateY گرفته است، به این معنی است که انیمیشن در راستای محور Y حرکت میکند، مقادیر valueFrom و valueTo برابر با مقادیر شروع و انتها هستند، با قرار دادن مقدار repeatMode به reverse و repeatCount به infinite ، انیمیشن برای همیشه در حلقه قرار میگیرد و تا زمانیکه VectorDrawable وجود دارد ادامه خواهد یافت، duration به 250 مقدار داده شده است که زمان انیمیشن را بر حسب میلی ثانیه مشخص میکند.
برای قرار دادن انیمیشن در drawable، نیاز داریم که یک فایل XML جدید به نام animated-vector بسازیم، کد زیر برای فایل animated-cpu.xml استفاده شده است :
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vector_drawable_cpu">
 
    <target
        android:animation="@animator/pulse_top"
        android:name="top" />
 
    <target
        android:animation="@animator/pulse_right"
        android:name="right" />
 
    <target
        android:animation="@animator/pulse_left"
        android:name="left" />
 
    <target
        android:animation="@animator/pulse_bottom"
        android:name="bottom" />
</animated-vector>
وقتی که تمام XML شما آماده شده است، میتوانید از animated_cpu.xml در drawable به عنوان یک ImageView استفاده کنید.
<ImageView
    android:id="@+id/cpu"
    android:layout_width="64dp"
    android:layout_height="64dp"
    android:src="@drawable/animated_cpu" />
برای شروع انیمیشن، باید یک جایگزین یا instance از Animatable از ImageView بسازیم و آن را Start کنیم.
ImageView mCpuImageView = (ImageView) findViewById( R.id.cpu );
Drawable drawable = mCpuImageView.getDrawable();
if (drawable instanceof Animatable) {
    ((Animatable) drawable).start();
}
بعد از اینکه start فراخوانی شد، سیم های CPU با کمی کد Java شروع به حرکت خواهند کرد.

3. تغییر شکل دادن Vector Drawables

یک استفاده ی مناسب از VectorDrawable این است که یک عکس را تغییر شکل دهیم، مانند یک آیکن اکشن بار که از یک همبرگر به یک فلش تغییر جهت پیدا میکند، برای انجام این کار، هر دو مسیر مبدا و مقصد باید از یک فرمت کد یکسان پیروی کنند، برای مثال، یک left_arrow و یک right_arrow در کد زیر به وجود آورده ایم :
<string name="left_arrow">M300,70 l 0,70 -70,-70 0,0 70,-70z</string>
<string name="right_arrow">M300,70 l 0,-70 70,70 0,0 -70,70z</string>
سپس، باید یک left_arrow در drawable بسازید، ما نام این فایل را vector_drawable_left_arrow.xml می نامیم :
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600" >
 
    <path
        android:name="left_arrow"
        android:fillColor="#000000"
        android:pathData="@string/left_arrow"/>
</vector>
تفاوت اصلی بین انیمیشن CPU و تغییر شکلی که در اینجا داریم این است که در اینجا فایل animator_left_right_arrow.xml را نیز باید بسازیم :
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 
    <objectAnimator
        android:duration="1000"
        android:propertyName="pathData"
        android:valueFrom="@string/left_arrow"
        android:valueTo="@string/right_arrow"
        android:valueType="pathType"
        android:repeatMode="reverse"
        android:repeatCount="-1"/>
 
</set>
باید توجه کنید که valueFrom و valueTo مقادیری هستند که برای path data و برای چپ و راست بودن فلش استفاده شدند، valueType به pathType مقدار دهی شده است و propertyName به pathData مقداردهی شده است، وقتی که این مقادیر ست شوند animator میداند که چگونه از یک حالت به حالت دیگر تغییر جهت بدهد، زمانی که کار animator تمام شده است، باید VectorDrawable را با objectAnimator توسط یک animated-vector وصل کنید :
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vector_drawable_left_arrow">
 
    <target
        android:name="left_arrow"
        android:animation="@animator/animator_left_right_arrows" />
</animated-vector>
در نهایت، میتوانید به راحتی animated drawable را توسط یک ImageView در کد Java خود فراخوانی کنید و نمایش دهید :
<ImageView
    android:id="@+id/left_right_arrow"
    android:layout_width="64dp"
    android:layout_height="64dp"
    android:layout_below="@+id/cpu"
    android:src="@drawable/animated_arrow" />
mArrowImageView = (ImageView) findViewById( R.id.left_right_arrow );
drawable = mArrowImageView.getDrawable();
if (drawable instanceof Animatable) {
    ((Animatable) drawable).start();
}

نتیجه گیری

همانطور که دیدید، کلاس VectorDrawable اجازه میدهد که به راحتی آیکن های فوق العاده ای برای اپلیکیشن خود بسازیم، اما یادتان باشد کلاس VectorDrawable در این لحظه که این مقاله را مینویسم کاملا در اندروید 5 به بالا پشتیبانی میشود یعنی در اندروید Lollipop و نسخه های بالاتر از آن.

محمد یه دانشجوی فناوری اطلاعات هست که از سال 92 فعالیتش رو شروع کرد، در حال حاضر در زمینه ی برنامه نویسی تحت وب و اندروید و شبکه های ارتباطی سیسکو فعالیت میکنه .

نظرات و سوالات کاربران

ارسال پاسخ shahin
shahin
پنج شنبه ۱۴ مرداد ۱۳۹۵ ۲۱:۱۲
سلام
ممنون بابت سایت خوبتون اما میشه بگین ما این کد ها رو برای ساختن یه عکس از کجا باید گیر بیاریم
اینجوری نمیشه که از خودمون ....
ممنون میشم کمکم کنید...!!!