در دو بخش قیلی گرافیک در اندروید (اینجا و اینجا) گذشته با دو نوع از Drawable ها (عناصری که می توان آنها را «کشید») آشنا شدید. عکس و shape. در این فصل می خواهیم با یک نوع دیگر از drawable ها آشنا شویم: انتخاب کننده یا selector.
مقدمه
اگر یک دکمه در layout قرار دهید و روی آن کلیک کنید می بینید که دکمه در زمان کلیک شدن، حالتش عوض شده و حس فرورفتگی را القا می کند:
اما اگر تصویر یا رنگ پس زمینه دکمه را تغییر دهید، دیگر دکمه در زمان کلیک هیچ تغییری نمی کند و کاربر نمی داند که آیا دکمه را کلیک کرده است یا نه؟
قبل از این که وارد جزئیات بشویم، روش حل این مشکل در اندروید را توضیح می دهم.
روش اندروید
دکمه چندین وضعیت متفاوت دارند. «فشرده» فقط یکی از آنها است. دکمه می تواند «فعال» باشد یا نباشد، «فوکوس» شده باشد یا نباشد و …
عکس زیر وضعیت های متفاوت یک دکمه در تم پیش فرض اندروید را نشان می دهد:
(منبع عکس)
راه حل اندروید این است که به جای داشتن یک drawable به عنوان پس زمینه، چرا از drawable های متفاوت برای وضعیت های متفاوت استفاده نکنیم؟ مثلاً وقتی دکمه در حالت «فشرده» است، پس زمینه آن را عوض کنیم و عکس یا drawable متفاوتی نمایش دهیم تا کاربر متوجه شود که دکمه کلیک شده است.
راه حل خوبی به نظر می رسد ولی چطور از آن در برنامه های خودمان استفاده کنیم؟ پاسخ «انتحاب کننده» یا selector است که در ادامه این مطلب کار کردن با آن را خواهید آموخت!
ایجاد انتخاب کننده یا selector
برای ساختن یک selector دکمه ctrl+n را بزنید یا از منوی File گزینه New را انتخاب کنید:
Next را کلیک کنید و در مرحله بعد همانند عکس زیر، Resource Type را drawable انتخاب کنید. برای selector خود یک نام تعیین کنید و Root Element را از نوع selector انتخاب کنید و دکمه Finish را بزنید:
حالا فایل selector_button به شاخه drawable اضافه شده است:
اگر فایل فوق را باز کنید، محتوای آن شبیه قطعه کد زیر است:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > </selector>
حالا ببینیم چطور میتوانیم «حالت»های مختلف پسزمینه (یا background) را در این «انتخاب کننده» یا Selector تعریف کنیم.
۱- تعریف حالت فشرده: برای تعریف یک پسزمینه متفاوت برای وقتی که کاربر روی دکمه میزند خط زیر را به selector فوق اضافه میکنیم:
<item android:state_pressed="true" android:drawable="@drawable/button_pressed"/>
شکل کلی فایل تا این لحظه شبیه قطعه کد زیر است:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_pressed="true" android:drawable="@drawable/button_pressed"/> </selector>
۲- تعریف حالت عادی: حالت عادی زمانی است که دکمه در هیچ یک از وضعیتهای فشرده (pressed)، فوکوسدار (focused) و غیر فعال (disabled) نباشد. برای تعریف حالت عادی (normal) کافی است هیچ یک از وضعیتهای فوق را برای دکمه تعریف نکنیم. بعد از اضافه کردن حالت عادی یا نرمال شکل کلی selector ما شبیه کد زیر خواهد شد:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_pressed="true" android:drawable="@drawable/button_pressed"/> <item android:drawable="@drawable/button_normal"/> </selector>
نکته ۱: اندروید برای این که تشخیص بدهد کدام یک از وضعیتهایی که گفتیم در حال حاضر وضعیت دکمه است تا بتواند پسزمینه درست را نمایش دهد، وضعیتهای تعریف شده در انتخاب کننده یا selector را خط به خط بررسی میکند و در صورتی که یک مورد با وضعیت دکمه منطبق باشد دیگر موارد را بررسی نمیکند. بنابراین باید حالتهایی که ممکن است کمتر رخ دهند را بالاتر تعریف کنید. برای مثال حالت نرمال یا عادی هیچ وضعیتی ندارد بنابراین اگر اولین خط را به حالت نرمال اختصاص بدهید همیشه وضعیت دکمه با این حالت منطبق شده و بنابراین سایر حالتها اصلا بررسی نمیشوند و شما هیچ تغییری در وضعیت دکمه در حالتهای دیگر مثل فشرده (pressed) مشاهده نخواهید کرد.
نکته ۲: همانطور که بالاتر دیدید بعضی وقتها دو وضعیت همزمان رخ میدهند. مثلا ممکن است دکمهای focused باشد و همزمان غیر فعال (disabled). در این حالت یک وضعیت ترکیبی درست میکنیم که در آن state_focused مقدار true و state_enabled مقدار false دارد. طبق نکته قبلی این یک وضعیت نادر است و نسبت به وضعیتی که دکمه فعال است کمتر رخ میدهد، بنابراین این وضعیت را بالاتر از سایر حالتها قرار میدهیم:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:state_enabled="false" android:drawable="@drawable/btn_default_normal_disable_focused" /> ... android:drawable="@drawable/btn_default_normal_disable" /> </selector>
نکته ۳: کلیه وضعیتهای تعریف شده برای انتخاب کنندهها در اندروید اینها است:
لازم نیست که همه آنها را بدانید ولی یک نگاه به این لیست در درک مفهوم انتخاب کننده به شما کمک فراوانی خواهد کرد.
مثالی از یک انتخاب کننده کامل که همه وضعیتهای دکمه را در نظر گرفته است:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/btn_default_normal" /> <item android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/btn_default_normal_disable" /> <item android:state_pressed="true" android:drawable="@drawable/btn_default_pressed" /> <item android:state_focused="true" android:state_enabled="true" android:drawable="@drawable/btn_default_selected" /> <item android:state_enabled="true" android:drawable="@drawable/btn_default_normal" /> <item android:state_focused="true" android:drawable="@drawable/btn_default_normal_disable_focused" /> <item android:drawable="@drawable/btn_default_normal_disable" /> </selector>
این کد از کدهای منبع Android SDK برداشته شده است.
انتخاب کننده در سایر View های اندروید هم استفاده میشود و ممکن است وضعیتهای متفاوتی با وضعیتهای دکمه داشته باشد. برای مثال در چکباکس وضعیت «تیک خورده» یا checked هم بررسی میشود در حالی که دکمه یا Button چنین وضعیتی ندارد:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Enabled states --> <item android:state_checked="true" android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/btn_check_on" /> <item android:state_checked="false" android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/btn_check_off" /> <item android:state_checked="true" android:state_pressed="true" android:state_enabled="true" android:drawable="@drawable/btn_check_on_pressed" /> <item android:state_checked="false" android:state_pressed="true" android:state_enabled="true" android:drawable="@drawable/btn_check_off_pressed" /> <item android:state_checked="true" android:state_focused="true" android:state_enabled="true" android:drawable="@drawable/btn_check_on_selected" /> <item android:state_checked="false" android:state_focused="true" android:state_enabled="true" android:drawable="@drawable/btn_check_off_selected" /> <item android:state_checked="false" android:state_enabled="true" android:drawable="@drawable/btn_check_off" /> <item android:state_checked="true" android:state_enabled="true" android:drawable="@drawable/btn_check_on" /> <!-- Disabled states --> <item android:state_checked="true" android:state_window_focused="false" android:drawable="@drawable/btn_check_on_disable" /> <item android:state_checked="false" android:state_window_focused="false" android:drawable="@drawable/btn_check_off_disable" /> <item android:state_checked="true" android:state_focused="true" android:drawable="@drawable/btn_check_on_disable_focused" /> <item android:state_checked="false" android:state_focused="true" android:drawable="@drawable/btn_check_off_disable_focused" /> <item android:state_checked="false" android:drawable="@drawable/btn_check_off_disable" /> <item android:state_checked="true" android:drawable="@drawable/btn_check_on_disable" /> </selector>
در مطالب بعدی مبحث گرافیک در اندروید را بیشتر واشکافی خواهیم کرد.
ایول بازم آموزشارو ادامه میدین!
خیلی ممنون
سلام دوست عزیز من کاربر جدید سایتتون هستم و از این بابت خیلی خوشحال
این مطلب دقیقا به مشکل من مربوط بود و بعد از کلی گشتو گذار پیداش کردم اما متاسفانه بعد از طی مراحل فوق با اروری در زمان اجرا مواجه میشم که به تکه کد زیر ارور میده
@drawable/btn_default_normal
البته به سایر حالتام گیر میده
ممنون میشم بهم کمک کنید
سلام
آیا فایل این drawable را در منابع (res) خودتان دارید؟ باید فایلی به همین نام در پوشههای drawable داشته باشید.
دست شما درد نکنه، آموزش ها عالیه.
کاش مثل شما تو ایران زیاد بود که با همه وجود دانشتون رو ارائه میدید.
موفق باشید