صفر تا صد dp در Android

در این پست به مفاهیم کامل پیکسل (Pixel)، واحد dp و sp خواهیم پرداخت. خواندن این مقاله برای توسعه‌دهندگان اندروید در هر سطحی و همچین طراحان گرافیکی که قصد تولید محتوی برای این پلتفرم دارند توصیه می‌شود. در هنگام کار با اکثر همکاران عدم درک اولیه از برخی موارد در اندروید برای من بسیار تعجب برانگیز است! به همین دلیل در هر پست هدف من درک موارد مهم و تمرین کردن آن با شما است تا بتوانید با خواندن مقالات رسمی و قدرت ذهنی خود آن را گسترش دهید و پیاده‌سازی کنید.نسخه انگلیسی مقاله:لینک Mediumکیفیت عکس مناسب در اندروید چگونه به دست می‌آید؟پیکسلتمامی صفحات نمایش که اطلاعات بر روی آن نمایش داده می‌شود، از اجزای ریز مربع شکل به نام پیکسل تشکیل شده‌اند. بزرگی یا کوچکی این واحد‌ها به تعداد پیکسل‌ها و اندازه صفحه نمایش مرتبط است، اگر غیر این است چگونه صفحه نمایش یک موبایل با رزولوشن 1080x1920 با صفحه نمایش یک کامپیتور خانگی با رزولوشن 1920x1080 هر دو دارای تعداد پیکسل‌های یکسانی هستند؟ این دو صفحه دارای اندازه متفاوت پیکسل و در نتیجه غلظت‌های مختلف پیکسلی هستند.یک پیکسل (مربع سفید)منظور از رزولوشن (Resolution) چیست؟به تصویر زیر توجه کنید:4 x 4 = 16عرض این مربع 4 پیکسل کشیده و طول آن 4 پیکسل کشیده می‌باشد و مجموعا دارای 16 پیکسل می‌باشد، به دو عدد 4x4 میزان رزولوشن آن گفته می‌شود.منظور از غلظت (Density) چیست؟غلظت نمایش دهنده میزان وجود چیزی در فضای مشخص می‌باشد.در مبحث کار با صفحه‌های نمایش ما از واحد پیکسل در هر (یک) اینچ (Pixel Per Inch) استفاده می‌کنیم.این مربع دارای غلظت چهار پیکسل در هر اینچ می‌باشد.این مربع دارای غلظت دو پیکسل در هر اینچ می‌باشد.این مربع دارای غلظت دو پکیسل در هر اینچ می‌باشد.پیکسل در (یک) اینچ با نماد ppi نمایش داده می‌شود ولی در پلتفرم اندروید از نماد dpi که به معنای نقطه در هر اینچ (dots per inch) است، استفاده می‌شود. پیکسل مربع است و نقطه نیست، دلیل استفاده از این نماد کمی عجیب است، دوستانی که Photoshop کار کردن با نماد ppi آشنا هستند.محاسبه غلظت پیکسلی دستگاهگوشی خود را برای یافتن مواردی که در بالا گفته شد آماده کنید. در این آموزش من از دستگاه فیزیکی خود با مشخصات زیر استفاده می‌کنم:Galaxy A5 2017 Screen Resolution: 1080x1920 Physical Size: 5.2 inchسایز صفحه نمایش هر دستگاهی معمولا به صورت مورب به شما داده می‌شود.طبق قوانین فیثاغورث برای محاسبه تعداد پیکسل‌های موجود بر روی خط فرضی 5.2 اینچی داریم:c = ~ 2200 (تعداد پیکسل‌ها بر روی خط 5.2 اینچی) 2200 / 5.2 = ~ 424 dpi (غلظت دستگاه)DP و SPنمونه اولدر این قسمت می‌خواهیم دکمه‌ای که را بر روی دو صفحه نمایش مختلف با غلظت‌های متفاوت ولی رزولوشن یکسان نمایش دهیم:رزولوشن برابر | غلظت متفاوتحجم دکمه بر روی مربع راست کمتر از دکمه سمت چپ می‌باشد. اگر مربع ما کوچکتر از قبل شود نتیجه چه خواهد شد؟ آیا کاربر می‌تواند به راحتی بر روی آن کلیک کند؟ برای حل این مشکل از واحدی برای ثابت نگه داشتن حجم دکمه و هر View دیگری بر روی اندروید استفاده می‌کنیم که به غلظت پیکسلی توجهی ندارد:dp/dip = density-independent pixel = پیکسل فارغ از غلظت sp = scale-independent pixel = پیکسل فارغ از تناسبواحد dp که برای تمامی View ها استفاده می‌شود توسط فرمول زیر محاسبه می‌شود:dp = px * (160 / dpi)دلیل وجود عدد 160 در این معادله چیست؟در اندروید 160 غلظت پیکسلی است که در آن هر یک پیکسل برابر یک dp می‌باشد. به این عدد غلظت پایه هم گفته می‌شود.واحد sp چیست؟این واحد دقیقا همانند dp می‌باشد ولی فقط برای سایز نوشته‌ها در اندروید استفاده می‌شود، تنها تفاوت آن با dp این است که اگر کاربر در تنظیمات گوشی خود سایز نوشته‌های سیستم عامل را تغییر داده باشد در اپلیکیشن شما هم اعمال خواهد شد.با فرض اینکه مربع راست دارای غلظت پیکسلی 320 و مربع سمت چپ دارای غلظت پیکسلی 160 می‌باشند با جایگذاری عدد 1dp در معامله میزان پیکسل مورد نیاز بر روی هر صفحه نمایش برای ثابت نگه داشتن سایز دکمه را محاسبه می‌کنیم:مربع سمت راست:1dp = 2px => (2x2) px * 2 = (4x4) px سایز دکمهمربع سمت چپ:1dp = 1px => (2x2) px * 1 = (2x2) px سایز دکمهدکمه سمت راست حجم برابری با دکمه سمت چپ دارد.با توجه به نتیجه به دست آمده متوجه می‌شویم که با افزایش غلظت پیکسلی بر روی صفحه نمایش تعداد پیکسل‌های Image یا View مورد نظر افزایش می‌یابد تا بر روی همه صفحات نمایش اندازه یکسانی داشته باشیم.نمونه دومبرای نمایش یک عکس با رزولوشن 4x2 با نتیجه زیر رو به رو خواهیم شد:اندازه برابر | غلظت متفاوتطراحان همیشه با واحد پیکسل تصاویر را تولید و برای شما ارسال می‌کنند. برای حل این مشکل اندروید برای ثابت نگه داشتن حجم تصاویر از پوشه‌هایی استفاده می‌کند که دارای غلظت پیکسل‌های متفاوتی هستند:ldpi: 0.75x or 75% (~120 dpi) (این غلظت از دور خارج شده است)mdpi: 1x or 100% (~160 dpi)hdpi: 1.5x or 150% (~240 dpi)xhdpi: 2x or 200% (~320 dpi)xxhdpi: 3x or 300% (~480 dpi)xxxhdpi: 4x or 400% (~640 dpi)nodpi (فاقد غلظت)تصاویر همیشه در پوشه drawable قرار می‌گیرند، برای ساخت این پوشه با غلظت‌های متفاوت موارد بالا را به عنوان پسوند آن اضافه می‌کنیم، مثلا drawable-xhdpiمعنای این پوشه‌ها چیست؟با قرار دادن تصویر خود در این پوشه‌ها به اندروید اعلام می‌کنید من سایز تصویر خودم را با توجه به غلظت مورد نظر تغییر داده‌ام و لطفا هنگام استفاده از تصویر آن را از نظر اندازه تغییر نده!اگر من عکسی با سایز 24x24 پیکسل در mdpi قرار دهم پس باید در سایر پوشه‌ها:hdpi = 32x32 px (x1.5)xhdpi = 48x48 px (x2)xxhdpi = 72x72 px (x3)اگر فقط تصویر خودم را در پوشه mdpi قرار دهم چه اتفاقی می‌افتد؟اگر تصویر خود را در یکی از پوشه‌ها قرار ندهید از نزدیکترین پوشه‌ دریافت و تغییر سایز داده می‌شود.فرآیند تغییر سایز شامل عملیات زمان‌بر و همچنین احتمال کاهش کیفیت عکس می‌شود، سعی کنید تصاویر خود را برای همه پوشه‌ها آماده کنید.اگر عکس 24x24 خود را در پوشه mdpi قرار دهم و گوشی کاربری دارای غلظت xhdpi باشد، سیستم عامل با تکنیک‌های پردازش تصویر تعداد پیکسل‌های آن را به 48x48 می‌رساند.پوشه drawable خام نیز همانند drawable-mdpi دارای غلظت پایه (160dpi) می‌باشد.اگر تصویر خود را فقط در پوشه nodpi قرار دهم چه اتفاقی خواهد افتاد؟تصاویری که در این پوشه قرار دارند به همان سایز پیکسلی وارد برنامه خواهند شد، برای جلوگیری از ارور معروف OutOfMemory بهتر است که قبل از وارد کردن تصویر به مموری آن را تغییر اندازه دهید.با دو برابر کردن پیکسل‌های تصویر چالش بر طرف می‌شوددر پشت غلظت پیکسلی هر پوشه علامتی با نشان ~ دیده می‌شود و به این معناست که این اعداد حدودی می‌باشند، دستگاه شما ممکن است عددی نزدیک به این غلظت‌ها داشته باشد. این که تصویر مورد نظر برای دستگاه شما از کدام پوشه دریافت می‌شود بستگی به نظر سازنده دستگاه دارد، مثلا اگر غلظت پیکسلی شما برابر 390 باشد ممکن است در زمره پوشه xhdpi یا xxhdpi قرار بگیرید و میزان scale شدن تصویر هم عددی به غیر از اعداد داده شده باشد.دسترسی به مشخصات دستگاهGithub Gistval density = resources.displayMetrics.density val densityDpi = resources.displayMetrics.densityDpi val heightPixels = resources.displayMetrics.heightPixels val widthPixels = resources.displayMetrics.widthPixels val scaledDensity = resources.displayMetrics.scaledDensity