Google
خانه / آموزش / آیا یک dp یک pixel است؟

آیا یک dp یک pixel است؟

سلام. مبحث امروزمان در مورد پشتیبانی برنامه از گوشی ها با سایز های گوناگون می باشد. شاید برای شما هم این سوال پیش آمده باشد و هدف من یافتن پاسخ مناسبی برای این دو سوال است:

که چرا برنامه من در گوشی های مختلف یکسان به نظر نمی رسد؟؟

آیا راهی علمی و نسبتاً دقیق برای پیاده سازی طرح طراح بدون سعی و خطا وجود دارد؟؟

شاید بصورت چشمی و دستی تغییراتی را اعمال می کنید و به نتیجه مطلوب می رسید و یا شاید هم مثل من برای آن راه کاری پیدا کرده اید.

مشکل کجاست؟

مشکل از آنجایی پیش آمده که تولید کننده گان زیادی برای گوشی های اندروید وجود دارند و هرکدام گوشی های متنوعی با سایز گوناگون و کیفیت تصویر گوناگون تولید می کنند. این مشکل در آیفون وجود ندارد و تنوع گوشی های آن بسیار پایین است. البته ما می توانیم این تهدید را به راحتی به فرصت تبدیل کنیم. در این مقاله تلاش می کنم تا استانداردهای گوگل را باهم برسی کرده و راهکار مناسبی ارائه دهیم. پس تا آخر این مطلب با من باشید!

 

اصطلاحات و مفاهیم

Screen density

تراکم صفحه به معنای تعداد نقاط موجود در صفحه برای نمایش بر اینچ می باشد.(از آنجایی که اکثر واحد های اندروید به اینچ است، ما هم با همین واحد کار خواهیم کرد. ) صفحه با تراکم low یعنی صفحه ای که در فضای فیزیکی آن تعداد پیکسل های کمی در مقایسه با صفحات normal و high وجود دارد. جزو مشخصات هرگوشی یک مشخه به عنوان تراکم تصویر با واحد dpi موجود است. به عنوان مثال گوشی samsung galaxy s6 دارای تراکم پیکسلی ۵۵۷ dpi است. ( واحد dpi و ppi هردو برای تراکم هستند و در صفحه موبایل هردو به یک معنا هستند. ) این واحد ربطی به سایز صفحه ندارد و ممکن است گوشی بزرگی باشد که تعداد پیکسل های آن کم باشد و گوشی کوچکی داشته باشیم که تراکم پیکسلی بسیار بالایی داشته باشد. بالعکس آن هم صادق است.

Resolution

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

Density-independent pixel (dp)

واحد مجازی و جایگزین پیکسل است  از آن جهت مشخص کردن اندازه ها و فاصله ها استفاده کنیم. هدف از تعریف dp ایجاد واحدی مستقل از تراکم صفحه است تا بتوان با استفاده از آن واحد در تمامی صفحات اندازه یکسانی داشته باشیم. حال ببینیم dp از کجا امده است؟

همانطور که در بالا اشاره شد تراکم های پیکسلی گوناگونی برای گوشی های اندروید وجود دارد و گوگل برای ساده کردن این تعداد زیاد، آنها را به دسته هایی تقسیم بندی کرده و یکی را یعنی ۱۶۰ dpi را به عنوان شاخص گوشی ها در نظر گرفته است. این دسته بندی به شکل زیر است:

1NXYH

 

بازه کامل تر با نمایی دیگر را ملاحظه فرمایید. همانطور که می بینید برای راحتی کار از هر بازه یک عدد را به عنوان نماینده آن بر می گزینیم و با آن نام صدا می زنیم. مثلا تمام گوش هایی که تراکم تصویری آنها بین ۱۰۰dpi و ۱۴۰dpi باشد از نظر ما ۱۲۰dpi بوده و در بازه ldpi یا low-dpi قرار می گیرد.
android_dpi_categories_chart_2013

بازه ها بطور دقیق تر عبارتند از: ( میانگین معیار بازه تا معیار بازه بعدی )

ldpi    ۱۰۰ – ۱۳۹
mdpi    ۱۴۰ – ۱۹۹
hdpi    ۲۰۰ – ۲۷۹
xhdpi   ۲۸۰ – ۳۶۹
xxhdpi   ۳۷۰ – ۵۵۹
xxxhdpi      ۵۶۰ – x

حال بر می گردیم به تعریف dp. بسیار ساده است! یک dp برابر است با دقیقاً یک پیکسل وقتی که dpi ما ۱۶۰ باشد.  وقتی در اندازه هایمان از dp استفاده کنیم خود اندروید آن را طوری محاسبه می کند که این اندازه تقریباً در تمامی گوشی ها یکسان به نظر برسد و طبق همین گفته با تقریب خوبی همیشه یک اینچ برابر ۱۶۰dp در هر گوشی می شود.  فرمول محاسبه pixel از روی dp بدین صورت است:

px = dp * (dpi / 160)

dp / dpi = inch پس یعنی ۱۶۰dp در در گوشی

حال این به چه معنی است؟ این فرمول می گوید مثلا اگر مارجین را در طراحی ۱۶dp بدهیم در گوشی با mdpi همان ۱۶px می شود. در گوشی hdpi برای نمایش این ۱۶dp از (۱۶*(۲۴۰/۱۶۰)) = ۲۴px استفاده می کند تا طرح ما یکسان به نظر برسد. زیرا ضریب تراکم ما ۱ شد که ضربدر تعداد پیکسل به ۲۴ رسیدیم. با قرار دادن dpi ها در فرمول به ضرایب زیر می رسیم:

  • ldpi = 0.00625 * 120 -> 0.75
  • mdpi = 0.00625 * 160 -> 1.0
  • hdpi = 0.00625 * 240 -> 1.5
  • xhdpi = 0.00625 * 320 -> 2.0
  • xxhdpi = 0.00625 * 480 -> 3.0
  • xxxhdpi = 0.00625 * 640 -> 4.0

 

راهکار چیست؟

حال وقت آن می رسد که با دانستن اطلاعات بالا راهی مناسب جهت پیاده سازی برنامه در گوشی با صفحه نمایش های مختلف پیدا کنیم. راهی که خود گوگل پیشنهاد می دهد این است:

Explicitly declare in the manifest which screen sizes your application supports

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

که می گوید در گوشی های بزرگ قابل دسترس باشد و یا مثال دیگر:

که می گوید کوچکترین عرض ممکن ۳۲۰dp خواهد بود و در گوشی هایی که این شرایط را ندارند قابل ارائه نخواهد بود. مثلا با کد زیر برنامه ما فقط برای تبلت ها قابل دسترس خواهد کرد.

اطلاعات بیشتر در گوگل.

 

Provide different layouts for different screen sizes

بصورت پیش فرض اندروید layout ها و چیدمان ها را بر اساس سایز صفحه تغییر سایز می دهد. این تغییر اکثرا مشکلی ندارد اما در برخی موارد ممکن است خوب به نظر نرسد و لازم باشد که اندازه ها و چیده مان ها تغییر کنند. برای همین امر فولدر هایی داریم که می توان بر اساس آنها لیوت های گوناگون داشته باشیم تا در شرایط مختلف بر اساس سایز تصویر، مورد استفاده قرار گیرند. برای این کار کافی است که layout های مختلف را با نام یکسان در فولدرهای مختلف قرار دهیم. به عنوان مثال می توانید main.xml را با طراحی دیگر برای تبلت داخل فولدر  layout-sw600 قرار دهید و با این کار به اندروید می گوییم که اگر حداقل عرض صفحه ۶۰۰dp بود از layout های داخل این فولدر استفاده کن.

 

Provide different bitmap drawables for different screen densities

بطور پیش فرض اندروید تصاویر شما را جهت نمایش در سایز های گوناگون تغییر سایز می دهد. ولی همانطور که می دانیم این امر سبب می شود تا کیفیت نمایشمان خیلی خوب نباشد. بهتر این است که ورژن های متفاوتی از تصاویر و بیتمپ هایمان را در سایز های گوناگون قرار دهیم تا اندروید با توجه به dpi صفحه مناسب ترین را جهت استفاده انتخاب و با کمترین تغییر سایز مورد استفاده قرار دهد. همانطور که پیش تر گفتیم چون dpi ها دارای رنج هستند یعنی مثلاً از ۱۴۱dpi تا ۲۰۰dpi جزو ۱۶۰dpi قرار می گیرند و منابع یکسانی استفاده می شود، لذا ممکن است در گوشی ۲۰۰dpi یک تصویر کمی کشیده شده و سپس مورد استفاده قرار گیرد.

روش استفاده از منابع توسط اندروید بدین صورت است:

res-selection-flowchart

۱- اول سیستم باتوجه به dpi گوشی وارد فولدر منابع می شود و اگر بتواند منابع را از داخل آن بر می دارد. به این پوشه ها توصیف کننده های اندازه می گویند. ( size qualifiers ) اگر نتوانست وارد پوشه منابع با اولویت بعدی می شود. سپس درصورت نیاز با اعمال تغییر سایز اندک مورد استفاده قرار می دهد. پوشه های منابع drawable بصورت زیر نامگذاری می شوند:

که بخش های آن عبارتند از:

Locale = en-GB
Screen orientation = port
Screen pixel density = hdpi
Touchscreen type = notouch
Primary text input method = 12key

۲- درصورتی که منبع مورد نظر در dpi ما یافت نشد، اندروید تصویر پیش فرض را بر می دارد و با تغییر سایز از آن استفاده می کند. منظور از پیش فرض همان منابعی هستند که در پوشه drawable/ قرار گرفته اند.

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

Configuration qualifiers

مثال:

توصیف کننده های جدیدی وجود دارند که بر اساس dp هستند. مثلا sw600dp می گوید دیوایس هایی که حد اقل عرض آنها ۶۰۰dp باشد. ( فرمول تبدیل dp  از روی dpi و تعداد px را در اوایل مقاله گفته ایم.)

Configuration qualifiers new

dp = px / (dpi / 160)

و کد آن:

اگر بخواهیم دیوایس ها را بر اساس عرض به dp تقسیم بندی کنیم:

و مثال:

البته موارد بیشتری نیز وجود دارد که لیست تمامی توصیف کننده ها می توانید در اینجا ببینید.

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

 

راهکار پیشنهادی

پیشنهاد خود گوگل این است که:

  1. استفاده از wrap_content، match_parent و  dp برای مشخص کردن ابعاد در xml فایل های layout
  2. عدم استفاده از واحد پیکسل آن هم بصورت هارد کد شده. ( یعنی ثابت :: مثلا ۱۰۰px )
  3. عدم استفاده از AbsoluteLayout که البته منسوخ شده است.
  4. فراهم کردن تصاویر جایگزین در سایزهای گوناگون برای صفحه نمایش های مختلف.

 

چطور طراحی را  پیاده سازی کنیم؟ تبدیل پیکسل از فتوشاپ به dp

بعد از دانستن مطالب بالا نوبت آن می رسد که بدانیم در طراحی واحدها را چگونه انتخاب کنیم تا پیداه سازی آن در گوشی بسیار راحت باشد؟ بهتر است بگوییم در این بخش می خواهیم ارتباط درستی با طراح داشته باشیم تا بعد از طراحی نیازی به سعی و خطا جهت بدست آوردن اندازه طرح داده شده نباشیم!

بسیار ساده است! ببینید آیا خودتان پیشنهادی دارید؟ روی این قضیه کمی تامل کنید و سپس ادامه مطلب را مشاهده فرمایید…

android2

  1. سایز گوشی که به عنوان معیار در دست دارید را به اینچ حساب کنید. ppi یا dpi آن هم مشخص است. ( مثلاً galaxy s6 557dpi است و اندازه آن ۴٫۵in در ۲٫۵in )
  2. در فوتوشاپ یک فایل جدید به اندازه سایز گوشی با اینچ درست کنید با تراکم پیکسلی گوشی. ( یعنی ۵۵۷ pixel/inch )
  3. حال هر طرحی زده شود هر پیکسل آن معادل یک dp است. بنابر این اگر طراح بخواهد فاصله ها را به پیکسل بدهد شما به راحتی می توانید همان اعداد را با واحد dp جایگزین کنید.
  4. از آنجا که گوشی شما در منطقه xxxhdpi قرار دارد یعنی دارای ضریب ۴ است. البته سایز های به dp هیچ نیازی به تغییر سایز ندارند و کار دولوپر با استفاده از واحد dp تقریباً تمام است و از اینجا به بعد گرافیست باید فایل های جایگزین را با در نظر گرفتن ضریب برای دسته بسازد. یعنی برای بدست آوردن xxhdpi کافی است تمامی فایل ها را ضرب در ۳/۴ بکنیم. اگر تصویری داریم که سایز آن ۴۰۰ در ۴۰۰ است رای تغییر سایز آن برای فولدرهای دیگر به این صورت می شود و تمامی این زحمات به عهده گرافیست است:
Screen resolution dpi Pixel ratio Image size (pixels)
xxxhdpi ۶۴۰ ۴٫۰ ۴۰۰×۴۰۰
xxhdpi ۴۸۰ ۳٫۰ ۳۰۰×۳۰۰
xhdpi ۳۲۰ ۲٫۰ ۲۰۰×۲۰۰
hdpi ۲۴۰ ۱٫۵ ۱۵۰×۱۵۰
mdpi ۱۶۰ ۱٫۰ ۱۰۰×۱۰۰

 

مثلا اگر تصویری استفاده کردیم که سایز اصلی آن در photoshop  به ۳۴۰×۵۴۰ است برای تغییر سایز آن برای فولدرهای دیگر به این صورت می شود :

Screen resolution dpi Pixel ratio Image size (pixels)
xxxhdpi ۶۴۰ ۴٫۰ ۳۴۰×۵۴۰
xxhdpi ۴۸۰ ۳٫۰ ۲۵۵×۴۰۵
xhdpi ۳۲۰ ۲٫۰ ۱۷۰×۲۷۰
hdpi ۲۴۰ ۱٫۵ ۱۲۷×۲۰۲
mdpi ۱۶۰ ۱٫۰ ۸۵×۱۳۵

 

نکته: یک نکته ای که وجود دارد این است که اندازه های انتخاب شده با تقریب خوبی درهمه دستگاه ها یکسان است. بخاطر اینکه dp بطور تقریبی است. چرا دقیق نیست؟ دلیل این است که برای dpi ها از بازه استفاده کردیم.  یعنی گفته ایم از ۱۴۰dpi تا ۱۹۹dpi را یکی و mdpi در نظر بگیر و همچنین بازه های دیگر. بله اگر تراکم ما دقیقاً ۱۶۰dpi باشد یک پیکسل و یک dp برابر می شود. اما فرض کنید در گوشی متفاوت که هردو در بازه ۲۴۰dpi یعنی hdpi هستند و یکی در مرز بالا یعنی مثلا ۲۷۹dpi قرار دارد و دیگری در مرز پایین یعنی ۲۰۰dpi در همه اینها نیز یک پیکسل یک dp در نظر گرفته می شود که همین امر باعث اییجاد اندازه تقریبی می شود. می دانیم طبق تعریف های انجام شده هر دو دریک بازه قرار می گیرند و از یک فرمول تبعیت می کنند. حال اگر طرحی داشته باشیم ۳۰۰dp باشد با فرمول dp/dpi = inch * 2.5 = cm  در اولی ۳۰۰/۲۷۹=۲٫۶۸cm و در دومی ۳۰۰/۲۰۰=۳٫۷۵cm که این اختلاف حدود یک سانتی متر وجود دارد. درصورتی که قرار بود اگر از dp استفاده کنیم در همه جا اندازه نمایشی یکسان باشد! پس بدانید که اگر کمی اختلاف بود بخاطر همین تقریب است. البته از نظر گوگل این قضیه ایرادی نداشته و در این مقاله فرض را بر این می گذاریم که آن تغییر و خطای ناشی از بازه ها را نادیده گرفتیم.

 

جمع بندی

همانطور که ملاحظه کردید می توان طوری طراحی را انجام داد که آن طراحی در گوشی های گوناگون یکسان دیده شود. بحث دیگری که داریم این است که گاهی لازم است اندازه ها یکسان نباشد. فرض کنید با استفاده از مطالب یاد شده کاری کردیم که دکمه ما در همه صفحه ها به یک نسبت و کاملا مطابق طراحی شد. اما در یک تبلت ۱۰ اینچی آیا یک دکمه بزرگ معنی خواهد داشت؟ و یا اینکه فرض کنید طوری طراحی کردیم که ۱۰ عدد آیتم صفحه قرار گیرد. در گوشی مبدا ۱۰ آیتم بسیار مناسب و خوب است اما در یک صفحه کوچک ۱۰ تا ایتم باعث می شود که آنقدر کوچک باشند که دیدن و یا انتخاب آنها بسیار سخت خواهد شد! پس یکسان نگه داشتن سایز و نسبت همیشه درست نیست و گاهی اوقات باید کلا طراحی و سایز ها عوض شوند. یعنی در فولدرهای منابع، dimension و layout های مختلفی قرار گیرند.

 

منابع:

https://developer.android.com/guide/practices/screens_support.html

https://developer.android.com/guide/practices/screen-compat-mode.html

https://developer.android.com/guide/practices/screens-distribution.html

https://developer.android.com/guide/practices/ui_guidelines/icon_design_launcher.html

https://developer.android.com/training/multiscreen/screendensities.html

https://developer.android.com/guide/topics/resources/providing-resources.html

۱۰ دیدگاه

  1. سلام خسته نباشی.میخواستم بدونم هر یک سانتی متر چند پیکسل میشه؟

  2. بسیار مفید بود.منون

  3. خیلی مفید بود.

  4. سلام خسته نباشید
    چطور می شود که تایپوگرافی در فتوشاپ را از حالت pt به px تبدیل کرد ؟

    • کافیست به قسمت
      Edit / Preferences / Unit & Rulers
      رفته و واحد را در قسمت Units بخش Type را به pixels تغییر دهید. اما از آنجا که اصولا نوشته ها را بصورت resources وارد پروژه نمی کنیم شاید بهتر باشد که متن را با کامپوننت های خود اندروید به پروژه اضافه کنید.

  5. عالی بود دستتون درد نکنه ❤❤

  6. سلام
    الهی خیر ببینی ، خدا پدرتو بیامرزه
    هر جا میگشتم راجع به این سایز ها اینقدر خوب توضیح نداده بودن
    واقعا ممنون

دیدگاهتان را ثبت کنید

آدرس ایمیل شما منتشر نخواهد شدعلامتدارها لازمند *

*

bigtheme