وجب زدن اندروید در اسنپ!

مقدمه

همیشه تو برنامه نویسی اندروید یک چالش گریبان‌گیر همه‌ی ما بوده. چالشی که موقع پیاده‌سازی دیزاین(طراحی) هر صفحه زمان زیادی میگیره و بچه‌های تیم QA هم موقع تست کلی ایرادهای متنوع پیدا میکنن و باید دوباره زمان بذاریم و رفعشون کنیم. این چالش چیزی نیست جز «سایزها و اندازه‌های مختلف گوشی‌های اندرویدی» که همه‌ی ما برنامه‌نویسای اندروید بارها باهاش دست و پنجه نرم کردیم.

اگر شما هم با این چالش رو به رو شدین و دوست دارید بدونید تو تیم اندروید اسنپ cab چطوری رفع شده این مقاله میتونه براتون جالب باشه.




يادآوری:

بهتره برای شروع مفاهیم Pixel, DPI, DSP و SP رو با هم مرور کنیم.

پیکسل (Pixel): کوچکترین عنصری که در یک صفحه نمایشگر آدرس‌دهی میشه تا تصویری رو نشون بده.

اDP یا Dots Per Inch (که بهش PPI یا Pixel Per Inch هم میگن): تعداد پیکسل‌هایی که در یک اینچ مربع قرار میگیرند و اصطلاحا رزولوشن گفته میشه. وقتی میگیم رزولوشن یه صفحه نمایشگر 160dpi هست یعنی در یک اینچ مربع از صفحه نمایشگر ۱۶۰ پیکسل وجود دارد.

طبق همین تعریف اگر بخوایم در نمایگشر شکلی بکشیم که ۲ پیکسل عرض و ۲ پیکسل طولش باشه همینطور که تو تصویر میبینید با توجه به رزولوشن نمایشگر اندازه‌ی شکل کوچک و بزرگ میشه.


https://www.altova.com/بع عکس
https://www.altova.com/بع عکس


از اونجایی که اتفاقی که می‌افتاده اصلا خوشایند نیست واحد دیگه ای به اسم DP یا DensityIndependent Pixels تعریف شد که همونطور که از اسمش مشخصه به ما این امکان رو میده که شکل مورد نظرمون تو رزولوشن‌های مختلف یکسان و یک‌اندازه دیده بشه.

SP یا Scalable Pixels : مانند DP مستقل از رزولوشن هست فقط با این تفاوت که فقط برای اندازه‌ی فونت‌ها استفاده میشه و مقداری که کاربر برای سایز فونت تو تنظیمات گوشی مشخص می‌کنه در این عدد ضرب میشه.

بر اساس تعریف‌های بالا وقتی بخوایم شکلی رو توی صفحه نمایش بدیم باید سایزش بر حسب پیکسل مشخص باشه. کاری که ما انجام میدیم اینه که در فایل XML شکل رو بر اساس واحد DP یا SP قرار میدیم و با فرمول زیر ابعادش بر حسب پیکسل محاسبه میشه.

px = dp * (dpi/number_of_pixles)



مشکل یا چالش


به قول تریماگاسی، Obvious. مشکل این بود که محتوای صفحات حتی در نمایشگرهای کوچک هم به راحتی قابل نمایش باشن. یک راه کلی استفاده از دیزاین‌های متفاوت بر اساس رزولوشن‌های متفاوته ولی این راه حل همیشه پاسخگوی نیاز ما نیست و تو مواردی نمیتونیم اجزای رو عوض کنیم. مثلا در صفحه درخواست سفر و صفحه سفر، داشتن دیزاین‌های متفاوت برای رزولوشن‌های متفاوت عملا برای ما امکان‌پذیر نبود.

با استفاده از واحدهای DP و SP مشکل پیکسل‌ها و رزولوشن‌های مختلف برطرف میشه ولی مساله‌ی دیگه ابعاد متفاوت گوشی‌های اندرویده. راه حل متداول این مشکل پیاده‌سازی چند لایه‌ی مختلف برای یک صفحه بر اساس Smallest Screen Width هست و همونطور که اشاره کردم این کار منابع زیادی از نظر زمان و تعداد افراد مصرف می‌کنه.

تو دیوایس‌های بزرگ فاصله‌ی بین اجزای صفحه خیلی زیاد می‌شد و نوشته‌ها هم با توجه به بزرگی صفحه نمایش کوچک می‌شدن. تو دیوایس‌های کوچک هم به خاطر زیاد بودن اجزای صفحه، آیتم‌ها مثل اسپاگتی در هم فرو می‌رفتن. زمان زیادی از اعضای تیم صرف رفع کردن مشکلات دیزاین تو سایزهای مختلف می‌شد.



راه حل و ایده

ایده‌ی کلی از SDP الهام گرفته شده. به جای داشتن چند لایه‌ی مختلف، چند دایمنشن(Dimention) مختلف تو Smallest Screen Width متفاوت نوشتیم.

واحد جدیدی به اسم RSP یا Responsive Scalable Pixels و RDP یا Responsive Density-Independent Pixels ایجاد کردیم و اندازه‌ی مبنا رو ابعاد sw390dp در نظر گرفتیم و باقی swها رو با اختلاف مقیاس از این مبنا محاسبه کردیم.

یعنی در دایمنشن‌های مبنا هر یک DP یا SP برابر با یک RDP یا RSP هست.

https://gist.github.com/rvhamed/df280748eba23927bd68668ad4976b99

محاسبه‌ی باقی swها که بزرگتر از ۳۹۰ هستن به صورت زیر است :

base = 390, target = 420

dp = (target/base) * rdp

https://gist.github.com/rvhamed/6fae8483b3b7be845c4762e7b26e8607

و اما نتیجه‌ی کار؟

در تصویر زیر ۴ گوشی مختلف رو می‌بینید، دو گوشی بالا پیاده‌سازی یک صفحه‌ی نمونه با سایزهای SP و DP هستند و دو گوشی پایین پیاده‌سازی همون صفحه با سایزهای RSP و RDP. با استفاده از این روش اپلیکیشن اسنپ روی گوشی‌های مختلف با ابعاد و رزولوشن‌های متفاوت تا حد زیادی به یک شکل دیده میشه.

مقایسه DP با RDP
مقایسه DP با RDP


به عنوان آخرین نکته هم این رو بگم که ما ابعاد مستقیم رو داخل کد قرار نمیدیم و به جاش ابعاد رو داخل تم‌ها میذاریم و به صورت ویژگی یا attribute ازشون استفاده میکنیم. اینطوری ابعاد جدیدی که تعریف کردیم داخل کد نیست و کد تمیزتر به چشم میاد.

https://gist.github.com/rvhamed/e25c89a3768f48959ad9083332c75d5a


این مدل پیاده‌سازی در نسخه‌ی فعلی اسنپ استفاده نشده و قراره که در نسخه‌های بعدی ازش استفاده کنیم.



در آخر یه تشکر ویژه هم از سینا فرحزادی میکنم که کمک کرد این مقاله رو بنویسیم و نقش خیلی مهمی تو پیاده سازی این ایده داشت. ❤️

و یک تشکر ویژه هم از نازنین دست سری میکنم که تو ویراستاری مقاله کمک شایانی کرد. ❤️

امیدوارم این مقاله براتون مفید بوده باشه. ☺️ اگه سوالی داشتین میدونین کجا پیدام کنین. همه جا!