دستگاههای Android نهتنها اندازههای صفحهنمایش متفاوتی دارند (گوشی، رایانه لوحی، تلویزیون، و غیره)، بلکه صفحهنمایشهایی با اندازههای پیکسل متفاوت دارند. یک دستگاه ممکن است ۱۶۰ پیکسل در هر اینچ داشته باشد، درحالیکه دستگاه دیگری ۴۸۰ پیکسل را در همان فضا جای میدهد. اگر این تفاوتها را در تراکم پیکسل درنظر نگیرید، ممکن است سیستم تصاویرتان را مقیاسبندی کند و درنتیجه تصاویر تار شوند یا با اندازه اشتباه نشان داده شوند.
این صفحه به شما نشان میدهد که چگونه میتوانید برنامه خود را برای پشتیبانی از تراکمهای پیکسلی مختلف بااستفاده از واحدهای اندازهگیری مستقل از وضوح و ارائه منابع بیتمپ جایگزین برای هر تراکم پیکسلی طراحی کنید.
برای مروری بر این تکنیکها، ویدیو زیر را تماشا کنید.
برای اطلاعات بیشتر درباره طراحی داراییهای نماد، به دستورالعملهای نماد طراحی مواد مراجعه کنید.
استفاده از پیکسلهای مستقل از تراکم
از پیکسل برای تعریف فاصلهها یا اندازهها استفاده نکنید. تعریف ابعاد با پیکسل مشکلساز است زیرا صفحهنمایشهای مختلف تراکم پیکسلی متفاوتی دارند، بنابراین تعداد پیکسلهای یکسان با اندازههای فیزیکی متفاوتی در دستگاههای مختلف مطابقت دارد.
برای حفظ اندازه قابلمشاهده میانای کاربر در صفحههایی با تراکمهای مختلف، میانای کاربر را بااستفاده از پیکسلهای مستقل از تراکم (dp) بهعنوان واحد اندازهگیری طراحی کنید. یک دیپی یک واحد پیکسل مجازی است که تقریباً برابر با یک پیکسل در صفحهنمایش با تراکم متوسط است (۱۶۰ دیپیآی، یا تراکم «خط مبنا»). Android این مقدار را به تعداد مناسب پیکسلهای واقعی برای هر تراکم دیگر ترجمه میکند.
دو دستگاه را در شکل ۱ درنظر بگیرید. نمایی که ۱۰۰ پیکسل عرض دارد در دستگاه سمت راست بسیار بزرگتر بهنظر میرسد. نمایی که عرض آن ۱۰۰ dp تعریف شده است در هر دو صفحهنمایش با اندازه یکسان نشان داده میشود.
هنگام تعریف کردن اندازههای نوشتار، میتوانید بهجای آن از پیکسلهای مقیاسپذیر (sp) بهعنوان واحد استفاده کنید. واحد sp بهطور پیشفرض هماندازه dp است، اما براساس اندازه نوشتار ترجیحی کاربر تغییر اندازه میدهد. هرگز از sp برای اندازههای چیدمان استفاده نکنید.
برای مثال، برای مشخص کردن فاصله بین دو نما، از dp استفاده کنید:
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/clickme" android:layout_marginTop="20dp" />
هنگام مشخص کردن اندازه نوشتار، از sp استفاده کنید:
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp" />
تبدیل واحدهای dp به واحدهای پیکسل
در برخی موارد، باید ابعاد را برحسب dp بیان کنید و سپس آنها را به پیکسل تبدیل کنید. تبدیل واحدهای dp به پیکسلهای صفحهنمایش بهصورت زیر است:
px = dp * (dpi / 160)
توجه: هرگز این معادله را برای محاسبه پیکسلها کدگذاری سخت نکنید. درعوض، از
TypedValue.applyDimension()
استفاده کنید که انواع مختلفی از ابعاد (dp، sp، و غیره) را به پیکسل تبدیل میکند.
برنامهای را تصور کنید که در آن اشاره پیمایش یا پرتاب
پساز اینکه انگشت کاربر حداقل ۱۶ پیکسل حرکت کرد تشخیص داده میشود. در صفحه پایه، انگشت کاربر باید 16 pixels
/ 160 dpi حرکت کند که معادل ۱/۱۰ اینچ (یا ۲٫۵ میلیمتر) است تا اشاره تشخیص داده شود.
در دستگاهی
با نمایشگر تراکم بالا (۲۴۰ dpi)، انگشت کاربر باید
16 pixels / 240 dpi حرکت کند، که
برابر با ۱/۱۵ اینچ (یا ۱٫۷ میلیمتر) است. فاصله بسیار کوتاهتر است و
بنابراین برنامه نسبتبه کاربر حساستر بهنظر میرسد.
برای رفع این مشکل، آستانه اشاره را در کد بهصورت dp بیان کنید و سپس آن را به پیکسلهای واقعی تبدیل کنید. برای مثال:
کاتلین
// The gesture threshold expressed in dp private const val GESTURE_THRESHOLD_DP = 16.0f private var gestureThreshold: Int = 0 // Convert the dps to pixels, based on density scale gestureThreshold = TypedValue.applyDimension( COMPLEX_UNIT_DIP, GESTURE_THRESHOLD_DP + 0.5f, resources.displayMetrics).toInt() // Use gestureThreshold as a distance in pixels...
جاوا
// The gesture threshold expressed in dp private final float GESTURE_THRESHOLD_DP = 16.0f; // Convert the dps to pixels, based on density scale int gestureThreshold = (int) TypedValue.applyDimension( COMPLEX_UNIT_DIP, GESTURE_THRESHOLD_DP + 0.5f, getResources().getDisplayMetrics()); // Use gestureThreshold as a distance in pixels...
فیلد DisplayMetrics.density
ضریب مقیاس مورداستفاده برای تبدیل واحدهای dp به
پیکسل را براساس تراکم پیکسلی فعلی مشخص میکند. در صفحهنمایش با تراکم متوسط،
DisplayMetrics.density برابر با
۱٫۰ است و در صفحهنمایش با تراکم بالا برابر با ۱٫۵ است. در صفحه با تراکم بسیار بالا،
این مقدار برابر با ۲٫۰ است و در صفحه با تراکم پایین، برابر با ۰٫۷۵ است. این رقم توسط TypedValue.applyDimension() برای دریافت تعداد پیکسل واقعی صفحه فعلی استفاده میشود.
استفاده از مقادیر پیکربندی ازپیش مقیاسبندیشده
میتوانید از کلاس ViewConfiguration برای دسترسی به مسافتها، سرعتها، و زمانهای رایج استفادهشده توسط سیستم Android استفاده کنید. برای مثال،
فاصله برحسب پیکسل که چارچوب بهعنوان آستانه پیمایش استفاده میکند را میتوان
با getScaledTouchSlop() بهدست آورد:
کاتلین
private val GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).scaledTouchSlop
جاوا
private final int GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).getScaledTouchSlop();
روشهای موجود در ViewConfiguration که با پیشوند getScaled شروع میشوند
تضمین میکنند که مقداری را برحسب پیکسل برگردانند که صرفنظر از تراکم پیکسل فعلی بهدرستی نمایش داده شود.
ترجیح با گرافیک بُرداری
یک جایگزین برای ایجاد چندین نسخه با تراکم خاص از یک تصویر، ایجاد تنها یک گرافیک برداری است. گرافیکهای برداری بهجای استفاده از نقشههای بیتی پیکسلی، بااستفاده از XML برای تعریف مسیرها و رنگها تصویر ایجاد میکنند. به همین دلیل، گرافیکهای برداری میتوانند به هر اندازهای مقیاسبندی شوند بدون اینکه مصنوعات مقیاسبندی ایجاد شود، هرچند معمولاً برای تصویرسازیهایی مانند نمادها مناسبتر هستند تا عکسها.
گرافیکهای برداری اغلب بهصورت فایلهای SVG (نگارهسازی برداری مقیاسپذیر) ارائه میشوند، اما Android از این قالب پشتیبانی نمیکند، بنابراین باید فایلهای SVG را به قالب ترسیمی برداری Android تبدیل کنید.
میتوانید بااستفاده از استودیوی دارایی بُرداری در «استودیو Android»، بهصورت زیر SVG را به ترسیمی بُرداری تبدیل کنید:
- در پنجره Project، روی دایرکتوری res کلیک راست کنید و New > Vector Asset را انتخاب کنید.
- فایل محلی (SVG، PSD) را انتخاب کنید.
فایلی را که میخواهید وارد کنید پیدا کنید و هرگونه اصلاحی را که لازم است انجام دهید.
شکل ۲: وارد کردن SVG با «استودیو Android». ممکن است در پنجره Asset Studio خطاهایی ببینید که نشان میدهد ترسیمیهای برداری از برخی ویژگیهای فایل پشتیبانی نمیکنند. این موضوع مانع از وارد کردن فایل نمیشود؛ ویژگیهای پشتیبانینشده نادیده گرفته میشوند.
روی بعدی کلیک کنید.
در صفحه بعدی، مجموعه منبع را که میخواهید فایل در پروژهتان باشد تأیید کنید و روی تمام کلیک کنید.
چون از یک ترسیمی بُرداری میتوان در همه تراکمهای پیکسلی استفاده کرد، این فایل در فهرست راهنمای ترسیمیهای پیشفرض شما قرار میگیرد، همانطور که در سلسلهمراتب زیر نشان داده شده است. نیازی نیست از دایرکتوریهای مختص تراکم استفاده کنید.
res/ drawable/ ic_android_launcher.xml
برای کسب اطلاعات بیشتر درباره ایجاد گرافیک بُرداری، سند ترسیمی بُرداری را بخوانید.
ارائه کردن نقشههای بیتی جایگزین
برای ارائه کیفیت گرافیکی خوب در دستگاههایی با تراکم پیکسل متفاوت، چندین نسخه از هر نقشه بیتی را در برنامهتان ارائه دهید—یک نسخه برای هر محدوده تراکم، با وضوح متناظر. درغیراینصورت، Android باید نگاشت بیتی شما را مقیاسبندی کند تا فضای قابلمشاهده یکسانی را در هر صفحه اشغال کند، که منجر به مصنوعات مقیاسبندی مانند محو شدن میشود.
چندین دسته تراکم برای استفاده در برنامههایتان دردسترس است. جدول ۱ توصیفگرهای پیکربندی مختلف موجود و انواع صفحههایی را که بر آنها اعمال میشوند توصیف میکند.
جدول ۱. توصیفگرهای پیکربندی برای تراکمهای پیکسل مختلف.
| توصیفگر تراکم | شرح |
|---|---|
ldpi |
منابع برای صفحهنمایشهای با تراکم پایین (ldpi) (حدود ۱۲۰ نقطه در اینچ). |
mdpi |
منابع برای صفحهنمایشهای با تراکم متوسط (mdpi) (تقریباً ۱۶۰ نقطه در اینچ). این تراکم پایه است. |
hdpi |
منابع برای صفحهنمایشهای با تراکم بالا (hdpi) (~۲۴۰ نقطه در اینچ). |
xhdpi |
منابع برای صفحهنمایشهای با تراکم بسیار بالا (xhdpi) (~۳۲۰ نقطه در اینچ). |
xxhdpi |
منابع برای صفحهنمایشهای با تراکم بسیار بسیار بالا (xxhdpi) (تقریباً ۴۸۰ نقطه در اینچ). |
xxxhdpi |
منابع برای استفادههای با تراکم بسیار بسیار بسیار بالا (xxxhdpi) (~640 dpi). |
nodpi |
منابع برای همه تراکمها. این منابع مستقل از تراکم هستند. سیستم منابع برچسبگذاریشده با این واجدشرایط را بدون توجه به تراکم صفحهنمایش فعلی مقیاسبندی نمیکند. |
tvdpi |
منابع برای صفحههایی که جایی بین mdpi و hdpi هستند؛ تقریباً
~۲۱۳ dpi. این گروه بهعنوان گروه تراکم «اصلی» درنظر گرفته نمیشود. این مقدار بیشتر برای تلویزیونها درنظر گرفته شده است و اکثر برنامهها به آن نیاز ندارند—ارائه منابع mdpi و hdpi برای اکثر برنامهها کافی است و سیستم آنها را بهطور مناسب مقیاسبندی میکند. اگر لازم میدانید منابع tvdpi را ارائه دهید،
اندازه آنها را با ضریب ۱٫۳۳ * mdpi تعیین کنید. برای مثال، یک تصویر ۱۰۰×۱۰۰ پیکسلی برای
صفحهنمایشهای mdpi، در tvdpi برابر با ۱۳۳×۱۳۳ پیکسل است. |
برای ایجاد نقشه بیتی قابلترسیم جایگزین برای تراکمهای مختلف، نسبت مقیاسبندی ۳:۴:۶:۸:۱۲:۱۶ را بین شش تراکم اصلی دنبال کنید. برای مثال، اگر یک نقشه بیتی قابلرسم با اندازه ۴۸×۴۸ پیکسل برای صفحهنمایشهای با تراکم متوسط داشته باشید، اندازهها عبارتند از:
- ۳۶×۳۶ (۰٫۷۵ برابر) برای تراکم پایین (ldpi)
- ۴۸×۴۸ (۱٫۰ برابر خط پایه) برای تراکم متوسط (mdpi)
- ۷۲×۷۲ (۱٫۵ برابر) برای تراکم بالا (hdpi)
- ۹۶×۹۶ (۲٫۰ برابر) برای تراکم بسیار بالا (xhdpi)
- ۱۴۴×۱۴۴ (۳٫۰ برابر) برای تراکم بسیار بسیار بالا (xxhdpi)
- ۱۹۲×۱۹۲ (۴٫۰ برابر) برای تراکم بسیار بسیار بسیار بالا (xxxhdpi)
فایلهای تصویری تولیدشده را در زیرفهرست راهنمای مناسب
در res/ قرار دهید:
res/
drawable-xxxhdpi/
awesome_image.png
drawable-xxhdpi/
awesome_image.png
drawable-xhdpi/
awesome_image.png
drawable-hdpi/
awesome_image.png
drawable-mdpi/
awesome_image.png
سپس، هروقت به @drawable/awesomeimage ارجاع دهید،
سیستم نقشه بیتی مناسب را براساس dpi صفحهنمایش انتخاب میکند. اگر
منبعی با تراکم خاص برای آن تراکم ارائه نکنید، سیستم
بهترین تطابق بعدی را پیدا میکند و آن را برای تناسب با صفحه مقیاسبندی میکند.
نکته: اگر منابع ترسیمشدنیای دارید که نمیخواهید سیستم آنها را مقیاسبندی کند، مثلاً وقتی خودتان در زمان اجرا تنظیماتی را روی تصویر اعمال میکنید، آنها را در دایرکتوریای با توصیفگر پیکربندی nodpi قرار دهید.
منابعی که این واجدشرایط را دارند، مستقل از تراکم درنظر گرفته میشوند و
سیستم آنها را مقیاسبندی نمیکند.
برای اطلاعات بیشتر درباره توصیفگرهای پیکربندی دیگر و نحوه انتخاب منابع مناسب توسط Android برای پیکربندی صفحه فعلی، به نمای کلی منابع برنامه مراجعه کنید.
نمادهای برنامه را در دایرکتوریهای mipmap قرار دهید
مانند سایر داراییهای نقشه بیتی، باید نسخههای خاص تراکم نماد برنامهتان را ارائه دهید. بااینحال، برخیاز راهاندازهای برنامه نماد برنامهتان را تا ۲۵٪ بزرگتر از آنچه در دسته چگالی دستگاه خواسته شده است نمایش میدهند.
برای مثال، اگر دسته چگالی دستگاه xxhdpi باشد و بزرگترین نماد برنامهای که
ارائه میدهید در drawable-xxhdpi باشد، راهانداز برنامه این نماد را مقیاسبندی میکند،
که باعث میشود کمتر واضح بهنظر برسد.
برای جلوگیری از این اتفاق، همه نمادهای برنامهتان را بهجای دایرکتوریهای drawable در دایرکتوریهای mipmap قرار دهید. برخلاف
دایرکتوریهای drawable، همه دایرکتوریهای mipmap در APK حفظ میشوند، حتی
اگر APKهای مختص تراکم بسازید. این کار به برنامههای راهانداز اجازه میدهد بهترین
نماد وضوح را برای نمایش در صفحه اصلی انتخاب کنند.
res/
mipmap-xxxhdpi/
launcher_icon.png
mipmap-xxhdpi/
launcher_icon.png
mipmap-xhdpi/
launcher_icon.png
mipmap-hdpi/
launcher_icon.png
mipmap-mdpi/
launcher_icon.png
در مثال قبلی دستگاه xxhdpi، میتوانید نماد راهانداز با تراکم بالاتر را در فهرست راهنمای mipmap-xxxhdpi ارائه دهید.
برای دستورالعملهای طراحی نماد، به نمادهای سیستم مراجعه کنید.
برای دریافت راهنمایی درباره ساختن نمادهای برنامه، به ایجاد نمادهای برنامه با «استودیوی دارایی تصویر» مراجعه کنید.
توصیه برای مشکلات غیرمعمول تراکم
این بخش توضیح میدهد که Android چگونه مقیاسبندی را برای نقشههای بیتی در تراکمهای پیکسلی مختلف انجام میدهد و چگونه میتوانید نحوه ترسیم نقشههای بیتی در تراکمهای مختلف را بیشتر کنترل کنید. مگر اینکه برنامهتان گرافیک را دستکاری کند یا هنگام اجرا در تراکمهای پیکسلی مختلف با مشکل مواجه شده باشید، میتوانید این بخش را نادیده بگیرید.
برای درک بهتر اینکه چگونه میتوانید از تراکمهای متعدد هنگام دستکاری گرافیک در زمان اجرا پشتیبانی کنید، باید بدانید که سیستم چگونه به اطمینان از مقیاس مناسب برای بیتمپها کمک میکند. این کار به روشهای زیر انجام میشود:
- پیشمقیاسبندی منابع، مانند بیتمپهای قابلرسم
براساس تراکم صفحهنمایش فعلی، سیستم از هر منبع خاص تراکم از برنامهتان استفاده میکند. اگر منابع در تراکم صحیح دردسترس نباشند، سیستم منابع پیشفرض را بار میکند و آنها را درصورت نیاز بزرگ یا کوچک میکند. سیستم فرض میکند که منابع پیشفرض (منابعی که از دایرکتوری بدون توصیفگر پیکربندی هستند) برای تراکم پیکسلی پایه (mdpi) طراحی شدهاند و اندازه آن نقشههای بیتی را به اندازه مناسب برای تراکم پیکسلی فعلی تغییر میدهد.
اگر ابعاد منبع پیشمقیاسبندیشده را درخواست کنید، سیستم مقادیری را برمیگرداند که ابعاد را پساز مقیاسبندی نشان میدهند. برای مثال، نقشه بیتی که با اندازه ۵۰×۵۰ پیکسل برای صفحهنمایش mdpi طراحی شده است، در صفحهنمایش hdpi به اندازه ۷۵×۷۵ پیکسل مقیاسبندی میشود (اگر منبع جایگزینی برای hdpi وجود نداشته باشد)، و سیستم اندازه را به همین صورت گزارش میکند.
در برخی شرایط ممکن است نخواهید Android منبعی را پیشمقیاسبندی کند. آسانترین راه برای اجتناب از پیشمقیاسبندی این است که منبع را در فهرست راهنمای منبع با توصیفگر پیکربندی
nodpiقرار دهید. برای مثال:res/drawable-nodpi/icon.png
وقتی سیستم از نقشه بیتی
icon.pngاز این پوشه استفاده میکند، آن را براساس تراکم دستگاه فعلی مقیاسبندی نمیکند. - مقیاسبندی خودکار ابعاد و مختصات پیکسل
میتوانید با تنظیم
android:anyDensityروی"false"در مانیفست یا بهصورت برنامهنویسیشده برایBitmapبا تنظیمinScaledروی"false"، ابعاد و تصاویر پیشمقیاسبندی را غیرفعال کنید. در این حالت، سیستم بهطور خودکار هرگونه مختصات پیکسلی مطلق و مقادیر ابعاد پیکسلی را در زمان ترسیم مقیاسبندی میکند. این کار را برای اطمینان از اینکه عناصر صفحهنمایش تعریفشده با پیکسل همچنان تقریباً با همان اندازه فیزیکی نمایش داده میشوند که میتوانند در تراکم پیکسل پایه (mdpi) نمایش داده شوند، انجام میدهد. سیستم این مقیاسبندی را بهطور شفاف برای برنامه مدیریت میکند و ابعاد پیکسل مقیاسبندیشده را بهجای ابعاد فیزیکی پیکسل به برنامه گزارش میدهد.برای مثال، فرض کنید دستگاهی دارای صفحهنمایش WVGA با تراکم بالا است که ۴۸۰×۸۰۰ است و تقریباً هماندازه صفحهنمایش HVGA سنتی است، اما برنامهای را اجرا میکند که پیشمقیاسبندی را غیرفعال کرده است. در این حالت، سیستم هنگام درخواست ابعاد صفحهنمایش به برنامه «دروغ میگوید» و مقدار ۳۲۰×۵۳۳ را گزارش میکند که ترجمه تقریبی mdpi برای تراکم پیکسل است.
سپس، وقتی برنامه عملیات طراحی را انجام میدهد، مثلاً مستطیلی را از (۱۰،۱۰) تا (۱۰۰، ۱۰۰) نامعتبر میکند، سیستم مختصات را با مقیاسبندی آنها به مقدار مناسب تبدیل میکند و درواقع منطقه (۱۵،۱۵) تا (۱۵۰، ۱۵۰) را نامعتبر میکند. اگر برنامهتان مستقیماً نقشه بیتی مقیاسبندیشده را دستکاری کند، این مغایرت ممکن است باعث رفتار غیرمنتظره شود، اما این یک موازنه منطقی برای اطمینان از بهترین عملکرد ممکن برنامه درنظر گرفته میشود. اگر با این وضعیت مواجه شدید، تبدیل واحدهای dp به واحدهای پیکسل را بخوانید.
معمولاً پیشمقیاسبندی را غیرفعال نمیکنید. بهترین راه برای پشتیبانی از چند صفحهنمایش، دنبال کردن تکنیکهای پایهای است که در این صفحه شرح داده شده است.
اگر برنامهتان نقشههای بیتی را دستکاری میکند یا بهنحوی دیگر مستقیماً با پیکسلهای روی صفحه تعامل دارد، ممکن است لازم باشد مراحل بیشتری را برای پشتیبانی از تراکمهای پیکسلی مختلف انجام دهید. برای مثال، اگر با شمارش تعداد پیکسلهایی که انگشت از آنها عبور میکند به اشارههای لمسی پاسخ میدهید، باید بهجای پیکسلهای واقعی از مقادیر پیکسل مستقل از تراکم مناسب استفاده کنید، اما میتوانید مقادیر dp و px را به یکدیگر تبدیل کنید.
آزمایش روی همه تراکمهای پیکسل
برنامهتان را در چند دستگاه با تراکمهای پیکسلی مختلف آزمایش کنید تا مطمئن شوید واسط کاربر بهدرستی مقیاسبندی میشود. درصورت امکان، آزمایش روی دستگاه فیزیکی؛ اگر برای همه تراکمهای پیکسلی مختلف به دستگاههای فیزیکی دسترسی ندارید، از شبیهساز Android استفاده کنید.
اگر میخواهید روی دستگاههای فیزیکی آزمایش کنید اما نمیخواهید دستگاهها را بخرید، میتوانید از Firebase Test Lab برای دسترسی به دستگاهها در مرکز داده Google استفاده کنید.