یه بار برای همیشه، فرانت‌اندو اصولی یاد بگیر! یه بار برای همیشه، فرانت‌اندو اصولی یاد بگیر!
🎯 ثبت نام

اشیای قابل ترسیم (Drawable) در اندروید

این آموزش به شرح مفهوم Drawable ها و نحوه ی استفاده از آن ها در اندروید می پردازد.

آموزش Drawable

Drawable یک مفهوم کلی در اندروید برای هر فایل گرافیکی قابل ترسیم می باشد یا به عبارت دیگر drawable هر چیزی است که بتوان آن را کشید. به عنوان ساده ترین نمونه می توان به یک فایل گرافیکی (bitmap) اشاره کرد که در اندروید توسط کلاس BitmapDrawable در اختیار توسعه دهنده قرار می گیرد.
هر drawable در قالب یک فایل مجزا در مسیر res/drawable ذخیره می شود. معمولا فایل های drawable در قالب فایل های bitmap در وضوح مختلف داخل زیرپوشه های –mdpi ، hdpi- xhdpi – xxhdpi مسیر res/drawable ذخیره می شوند. ویزارد و راهنمای ساخت پروژه ی ADT این پوشه ها را خود به صورت پیش فرض ایجاد می کند. اگر bitmap ها در پوشه ی متفاوتی ذخیره شده باشند، سیستم اندروید خود تنظیمات دستگاه و اندازه ی صفحه نمایش را ارزیابی کرده و بر اساس آن گزینه ی مناسب را انتخاب می کند.
چنانچه عکس مورد نظر را در تمامی وضوح (تراکم پیکسلی و با کیفیت مناسب) نداشته باشید، در آن صورت سیستم اندروید تصویر مربوطه را جهت سازگاری کامل با صفحه نمایش دستگاه میزبان کوچک یا بزرگ می کند. البته این قابلیت ظاهر چندان مناسبی را به وجود نمی آورد چرا که در بیشتر موارد عکس مورد نظر تار شده و از وضوح و کیفیت مناسب برخوردار نخواهد بود.
علاوه بر فایل های گرافیکی، اندروید از drawable های مبتنی بر XML و 9-patch پشتیبانی می کند. drawable های که در فایل های XML تعریف می شوند به برنامه نویس این امکان را می دهد تا رنگ، حاشیه، شیب/طیف رنگ و گوشه ها را در قالب تگ shape و همچنین state (جهت تعریف عکس خاص برای هر وضعیت ای که view در آن قرار می گیرد)، transition (برای تعریف انیمیشن) فایل گرافیکی مورد نظر را تعریف کند.
به وسیله ی فایل های گرافیکی 9-patch می توان مشخص کرد که در صورت بزرگ تر بودن view میزبان، کدام بخش از فایل گرافیکی مورد نظر می بایست کشیده (بزرگتر) شود.
فایل های Drawable را می توان با کدهای Java نوشت. هر آبجکتی که توابع اینترفیس Drawable را پیاده سازی می کند را می توان به صورت فایل ترسیم شونده/Drawable در کد بکار برد.

آموزش استفاده از drawable ها در view ها

جهت دسترسی و اشاره به drawable ها در XML می توان از این ساختار استفاده نمود: @drawable/filename . در این ساختار نگارشی filename همان اسم فایل بدون پسوند می باشد. برای مثال جهت دستیابی به فایل drawable در مسیر res/drawable/hello.png و درج آن در پس زمینه ی UI، کافی است ساختار @drawable/hello را به صورت زیر استفاده نمایید.

1
2
<textview xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/hello" android:text="@string/hello_world"></textview>
<button></button>

می توان با کدنویسی drawable ها را به view ها اختصاص داد. بیشتر view ها این قابلیت را دارند که ID فایل منبع مورد نظر را به عنوان پارامتر ورودی بپذیرند. کد زیر نحوه ی تخصیص یک فایل drawable را به عنوان تصویر پس زمینه به ImageView نمایش می دهد.

1
2
3
ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageResource(R.drawable.hello);
<button></button>

آموزش بارگذاری Bitmap ها و drawable ها

جهت استفاده از bitmap ها در اندروید می توانید از کلاس Bitmap استفاده نمایید. در این بخش خواهید آموخت چگونه با کد جاوا آبجکت های Bitmap ایجاد نموده و سپس آن را به آبجکت های Drawable و بالعکس تبدیل نمایید.
این امکان برای شما وجود دارد که فایل bitmap موجود را با کدنویسی بارگذاری نموده و متعاقبا آن ها را به آبجکت های Drawable تبدیل کرد.
مثال زیر نمایش می دهد چگونه می توان یک آبجکت Bitmap در پوشه ی assets ایجاد نموده و آن را به المان رابط کاربری ImageView تخصیص داد.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
AssetManager manager = getAssets();
                // read a Bitmap from Assets
                InputStream open = null;
                try {
                        open = manager.open("logo.png");
                        Bitmap bitmap = BitmapFactory.decodeStream(open);
                        // Assign the bitmap to an ImageView in this layout
                        ImageView view = (ImageView) findViewById(R.id.imageView1);
                        view.setImageBitmap(bitmap);
                } catch (IOException e) {
                        e.printStackTrace();
                } finally {
                        if (open != null) {
                                try {
                                        open.close();
                                } catch (IOException e) {
                                        e.printStackTrace();
                                }
                        }
                }
<button></button>

همچنین می توانید به فایل های Drawable از پوشه ی res/drawable به صورت آبجکت های Bitmap در کد برنامه دسترسی پیدا کنید. کد زیر این قابلیت را به نمایش می گذارد.

1
2
                    Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_search);
<button></button>

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

1
2
3
4
Bitmap originalBitmap = <initial setup="">;
Bitmap resizedBitmap =
   Bitmap.createScaledBitmap(originalBitmap, newWidth, newHeight, false);
</initial><button></button>

به منظور تبدیل یک آبجکت Bitmap به Drawable می توانید کد زیر را بکار ببرید.

1
2
3
# Convert Bitmap to Drawable
Drawable d = new BitmapDrawable(getResources(),bitmap);
<button></button>

آموزش Drawable های مبتنی بر XML

آموزش Shape

Shape ها نیز یک نوع drawable هستند که در فرمت XML تعریف شده و به توسعه دهنده این امکان را می دهند تا آبجکت یا اشکال هندسی با رنگ، حاشیه و شیب رنگ تعریف نمایند.
می توانید این اشکال هندسی را به view های مورد نظر تخصیص داده و از آن ها در المان های رابط کاربری استفاده نمایید.
مزیت استفاده از shape در این است که خود را به صورت اتوماتیک به مقیاس مناسب تنظیم می کند.
کد زیر نمونه ای از یک Shape را نشان می دهد.

1
2
3
4
5
6
7
<!--?xml version="1.0" encoding="UTF-8" ?-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
                <stroke android:width="2dp" android:color="#FFFFFFFF"></stroke>
                <gradient android:endcolor="#DDBBBBBB" android:startcolor="#DD777777" android:angle="90"></gradient>
                <corners android:bottomrightradius="7dp" android:bottomleftradius="7dp" android:topleftradius="7dp" android:toprightradius="7dp"></corners>
</shape>
<button></button>

می توانید drawable مزبور را به ویژگی (property) background در فایل layout تخصیص داده و آن را به عنوان تصویر پس زمینه ی UI تنظیم نمایید.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--?xml version="1.0" encoding="utf-8" ?-->
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/myshape" android:orientation="vertical">
                <edittext android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content">
    </edittext>
                <radiogroup android:id="@+id/radioGroup1" android:layout_width="match_parent" android:layout_height="wrap_content">
                <radiobutton android:id="@+id/radio0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="@string/celsius">
        </radiobutton>
                <radiobutton android:id="@+id/radio1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/fahrenheit">
        </radiobutton>
    </radiogroup>
                <button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/calc" android:onclick="myClickHandler">
    </button>
</linearlayout>
<button></button>

آموزش Drawable های مبتنی بر state

می توان برای هر وضعیت یک drawable ویژه تعریف کرد و سپس بسته به وضعیت جاری، drawable مربوطه را به view تخصیص داد. برای مثال تکه کد زیر وضعیت دکمه را در نظر می گیرد و سپس با توجه به وضعیت آن، drawable مربوطه را به view اختصاص می دهد.

1
2
3
4
5
6
7
<!--?xml version="1.0" encoding="utf-8" ?-->
                <item android:drawable="@drawable/button_pressed" android:state_pressed="true"></item>
                <item android:drawable="@drawable/button_checked" android:state_checked="true"></item>
                <item android:drawable="@drawable/button_default"></item>
</selector>
<button></button>

آموزش Drawable هایی که طی انتقال جایگزین drawable دیگری می شوند (transition drawable)

شما می توانید در تگ transition، افکت انتقال و جابجایی را تعریف کرده و آن را در کد فعال نمایید. از این طریق یک تصویر طی transition جایگزین تصویری قبلی می شود.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!--?xml version="1.0" encoding="utf-8" ?-->
<transition xmlns:android="http://schemas.android.com/apk/res/android">
                <item android:drawable="@drawable/first_image"></item>
                <item android:drawable="@drawable/second_image"></item>
</transition>
final ImageView image = (ImageView) findViewById(R.id.image);
final ToggleButton button = (ToggleButton) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(final View v) {
                TransitionDrawable drawable = (TransitionDrawable) image.getDrawable();
                if (button.isChecked()) {
                        drawable.startTransition(500);
                } else {
                        drawable.reverseTransition(500);
                }
        }
});
<button></button>

آموزش Drawable های برداری/توسعه پذیر بدون از دست رفت کیفیت (vector drawable)

از ویرایش 5.0، اندروید به توسعه دهندگان این امکان را می دهد تا drawable های برداری/vector مانند فایل های SVG تعریف کنند. کد زیر کاربرد آن را در فایل vectordrawable.xml به نمایش می گذارد. استفاده از drawable های برداری این مزیت را دارد که خود را با توجه به تراکم پیکسلی (density) و کیفیت دستگاه میزبان تنظیم می کند.

1
2
3
4
5
6
<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="rotationGroup" android:pivotx="300.0" android:pivoty="300.0" android:rotation="45.0">
                <path android:name="v" android:fillcolor="#000000" android:pathdata="M300,70 l 0,-70 70,70 0,0 -70,70z"></path>
     </group>
 </vector>
<button></button>

از ویرایش 5.0، کلاس جدیدی به نام AnimatedVectorDrawable به کتابخانه های اندروید اضافه شد که به برنامه نویس اجازه می دهد تا drawable های برداری را با انیمیشن ترکیب کند (ویژگی های drawable را با انیمیشن های تعریف شده توسط ObjectAnimator یا AnimatorSet متحرک و پویا کند). برای مشاهده ی مثال هایی بیشتر می توانید به آدرس http://blog.sqisland.com/2014/10/first-look-at-animated-vector-drawable.html مراجعه نمایید.
برای استفاده از drawable های برداری در platform یا ورژن های قدیمی تر چارچوب نرم افزاری اندروید، می توانید از کتابخانه ی VectorDrawableCompat (یک کتابخانه که امکان استفاده از drawable های برداری در ورژن های قبلی اندروید را فراهم می آورد) استفاده نمایید.

آموزش Drawable animation (تعریف انیمیشن با بارگذاری یک drawable پس از دیگری)

می توانید animation drawable تعریف کرده و با استفاده از متد setBackgroundResource() آن را به View تخصیص دهید. اندروید به شما این امکان را می دهد تا drawable هایی را با حالت انیمیشن یکی پس از دیگری نمایش دهید.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- Animation frames are phase*.png files inside the
 res/drawable/ folder -->
                <animation-list android:id="@+id/selected" android:oneshot="false">
                <item android:drawable="@drawable/phase1" android:duration="400"></item>
                <item android:drawable="@drawable/phase2" android:duration="400"></item>
                <item android:drawable="@drawable/phase3" android:duration="400"></item>
 </animation-list>
ImageView img = (ImageView)findViewById(R.id.yourid);
img.setBackgroundResource(R.drawable.your_animation_file);
 // Get the AnimationDrawable object.
 AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();
 // Start the animation (looped playback by default).
 frameAnimation.start();
<button></button>

همچنین می توانید آبجکتی پیاده سازی کنید که از کلاس Drawable ارث بری کرده و توابع اینترفیس Animatable را پیاده سازی می کند.
Drawable های برداری را می توان با استفاده از کتابخانه ی VectorDrawableCompat در ورژن های قبلی های اندروید نیز بکار برد.

آموزش Drawable های nine-patch (فایل های ترسیم شونده ی منعطف با کناره های بسط پذیر)

تصور کنید یک عکس دارید و زمانی که شما این تصویر را می کشید، کناره یا لبه ی عکس تار می شود. حال اگر شما تصویری داشته باشید که وسط آن تغییر نکرده و ثابت بماند (با کشیدن تصویر تار نشود)، می توانید آن بخش هایی که با بزرگتر شدن عکس مات نمی شوند را 9-patch تعریف کنید. سیستم اندروید در زمان اجرای برنامه بخش های علامت گذاری نشده را از نظر اندازه تغییر نمی دهد، اما سایر بخش ها را کش داده و عکس را بزرگ می کند. بدین وسیله زمانی که تصویر برای کاربر به نمایش در می آید، کیفیت آن کاهش نمی یابد.
Drawable های 9-patch، فایل های ترسیم شونده تصویری هستند که یک پیکسل اضافی در حاشیه دارند. در بالا و سمت چپ می توانید ناحیه ای تعریف کنید که متناسب با view اندازه بندی و در صورت لزوم بزرگ می شوند. این ناحیه stretch area است.

Drawable های nine-patch

چنانچه drawable قرار است در یک view قرار گیرد که اجازه ی نوشتن بر روی آن را داشته باشد (همچون آبجکت Button)، در آن صورت می توانید در کناره های سمت راست و پایین ناحیه ای تعریف کنید که در آن متن امکان درج را داشته باشد.

ADT برنامه ای به نام draw9patch در پوشه ی android-sdk/tools ارائه می دهد که ساخت drawable های انعطاف پذیر و 9-patch را آسان می سازد.

آموزش Drawable های اختصاصی

می توانید drawable های اختصاصی تعریف کنید که برای نمایش در UI از Canvas API بهره می گیرند. می توانید با استفاده از تمامی توابع/Canvas API فایل های ترسیم شونده یا drawable را متناسب با نیاز خود تنظیم و طراحی کنید.

آموزش ساخت drawable های اختصاصی

پروژه جدید به نام com.vogella.android.drawables.custom ایجاد کرده و قالب آماده ی Empty Activity را برای توسعه ی پروژه ی خود انتخاب نمایید.
کلاس اختصاصی Drawable را به صورت زیر پیاده سازی نمایید.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.vogella.android.drawables.custom;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
public class MyRoundCornerDrawable extends Drawable {
        private Paint paint;
        public MyRoundCornerDrawable(Bitmap bitmap) {
                BitmapShader shader;
                shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,
                                Shader.TileMode.CLAMP);
                paint = new Paint();
                paint.setAntiAlias(true);
                paint.setShader(shader);
        }
        @Override
        public void draw(Canvas canvas) {
                int height = getBounds().height();
                int width = getBounds().width();
                RectF rect = new RectF(0.0f, 0.0f, width, height);
                canvas.drawRoundRect(rect, 30, 30, paint);
        }
        @Override
        public void setAlpha(int alpha) {
                paint.setAlpha(alpha);
        }
        @Override
        public void setColorFilter(ColorFilter cf) {
                paint.setColorFilter(cf);
        }
        @Override
        public int getOpacity() {
                return PixelFormat.TRANSLUCENT;
        }
}
<button></button>

برای استفاده از این کلاس در متن پروژه، فایل layout خود را به صورت زیر ویرایش نمایید.

1
2
3
4
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
                <imageview android:id="@+id/image" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_centerhorizontal="true" android:layout_centervertical="true" android:contentdescription="TODO"></imageview>
</relativelayout>
<button></button>

پیاده سازی کلاس MainActivity خود را به صورت زیر ویرایش نمایید. کد فرض را بر این می گذارد شما یک فایل bitmap به نام dog.png در پوشه ی drawable خود دارید.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.vogella.android.drawables.custom;
import java.io.InputStream;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ImageView;
public class MainActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                ImageView button = (ImageView) findViewById(R.id.image);
                InputStream resource = getResources().openRawResource(R.drawable.dog);
                Bitmap bitmap = BitmapFactory.decodeStream(resource);
                button.setBackground(new MyRoundCornerDrawable(bitmap));
        }
}
<button></button>
1395/12/08 7095 2725
رمز عبور : tahlildadeh.com یا www.tahlildadeh.com
نظرات شما

نظرات خود را ثبت کنید...