پشتیبانی از تراکم پیکسل های مختلف

دستگاه‌های اندرویدی نه تنها دارای اندازه‌های مختلف صفحه‌نمایش - گوشی، تبلت، تلویزیون و غیره- هستند، بلکه دارای صفحه‌نمایش‌هایی با اندازه‌های پیکسل متفاوت هستند. یک دستگاه ممکن است 160 پیکسل در هر اینچ داشته باشد، در حالی که دستگاه دیگر 480 پیکسل در همان فضا قرار می گیرد. اگر این تغییرات را در تراکم پیکسل در نظر نگیرید، سیستم ممکن است تصاویر شما را مقیاس‌بندی کند و در نتیجه تصاویر تار شوند، یا ممکن است تصاویر در اندازه اشتباه ظاهر شوند.

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

برای مشاهده کلی این تکنیک ها ویدیوی زیر را تماشا کنید.

برای اطلاعات بیشتر در مورد طراحی دارایی‌های نماد، دستورالعمل‌های نماد طراحی مواد را ببینید.

از پیکسل های مستقل از چگالی استفاده کنید

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

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

برای حفظ اندازه قابل مشاهده رابط کاربری خود در صفحه نمایش هایی با تراکم های مختلف، رابط کاربری خود را با استفاده از پیکسل های مستقل از چگالی (dp) به عنوان واحد اندازه گیری طراحی کنید. یک dp یک واحد پیکسل مجازی است که تقریباً برابر با یک پیکسل در یک صفحه نمایش با چگالی متوسط ​​است (160 dpi یا چگالی "پایه"). اندروید این مقدار را به تعداد مناسب پیکسل های واقعی برای چگالی یکدیگر ترجمه می کند.

دو دستگاه را در شکل 1 در نظر بگیرید. نمای با عرض 100 پیکسل در دستگاه سمت چپ بسیار بزرگتر به نظر می رسد. نمای تعریف شده به عرض 100 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 پیکسل تشخیص داده می‌شود. در صفحه پایه، انگشت کاربر باید 16 pixels / 160 dpi ، که برابر است با 1/10 اینچ (یا 2.5 میلی‌متر) حرکت کند، قبل از اینکه ژست تشخیص داده شود.

در دستگاهی با صفحه نمایش با تراکم بالا (240 dpi)، انگشت کاربر باید 16 pixels / 240 dpi حرکت کند، که برابر است با 1/15 اینچ (یا 1.7 میلی متر). فاصله بسیار کمتر است و بنابراین برنامه برای کاربر حساس تر به نظر می رسد.

برای رفع این مشکل، آستانه حرکت را در کد به صورت 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 برابر با 1.0 و در صفحه نمایش با چگالی بالا برابر با 1.5 است. در صفحه نمایش با تراکم فوق العاده بالا، برابر با 2.0 و در صفحه نمایش با تراکم پایین، برابر با 0.75 است. این شکل توسط TypedValue.applyDimension() برای بدست آوردن تعداد پیکسل واقعی برای صفحه فعلی استفاده می شود.

از مقادیر پیکربندی از پیش مقیاس شده استفاده کنید

می توانید از کلاس ViewConfiguration برای دسترسی به مسافت ها، سرعت ها و زمان های رایج سیستم اندروید استفاده کنید. برای مثال، فاصله پیکسل‌هایی که فریم‌ورک به‌عنوان آستانه پیمایش استفاده می‌کند را می‌توان با getScaledTouchSlop() بدست آورد:

کاتلین

private val GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).scaledTouchSlop

جاوا

private final int GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).getScaledTouchSlop();

روش‌هایی که در ViewConfiguration با پیشوند getScaled شروع می‌شوند تضمین شده‌اند که مقداری را در پیکسل‌ها برمی‌گردانند که بدون توجه به تراکم پیکسل فعلی به درستی نمایش داده می‌شوند.

گرافیک برداری را ترجیح دهید

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

گرافیک های برداری اغلب به صورت فایل های SVG (گرافیک برداری مقیاس پذیر) ارائه می شود، اما اندروید از این فرمت پشتیبانی نمی کند، بنابراین باید فایل های SVG را به فرمت قابل ترسیم برداری اندروید تبدیل کنید.

می‌توانید با استفاده از استودیوی Vector Asset Android Studio یک SVG را به یک وکتور قابل ترسیم تبدیل کنید:

  1. در پنجره Project ، روی دایرکتوری res راست کلیک کرده و New > Vector Asset را انتخاب کنید.
  2. فایل محلی (SVG، PSD) را انتخاب کنید.
  3. فایلی را که می خواهید وارد کنید پیدا کنید و تنظیمات را انجام دهید.

    تصویری که نحوه وارد کردن SVG در Android Studio را نشان می دهد
    شکل 2 : وارد کردن یک SVG با Android Studio.

    ممکن است متوجه برخی از خطاها در پنجره Asset Studio شوید که نشان می‌دهد نقشه‌های برداری برخی از ویژگی‌های فایل را پشتیبانی نمی‌کنند. این مانع از وارد کردن فایل نمی شود. ویژگی های پشتیبانی نشده نادیده گرفته می شوند.

  4. روی Next کلیک کنید.

  5. در صفحه بعدی، مجموعه منبعی را که می‌خواهید فایل را در پروژه خود قرار دهید تأیید کنید و روی Finish کلیک کنید.

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

    res/
      drawable/
        ic_android_launcher.xml
    

برای اطلاعات بیشتر در مورد ایجاد گرافیک برداری، مستندات قابل ترسیم برداری را بخوانید.

ارائه نقشه های بیت جایگزین

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

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

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

جدول 1. واجد شرایط پیکربندی برای تراکم پیکسل های مختلف.

تعیین کننده چگالی توضیحات
ldpi منابع صفحه نمایش با چگالی کم ( ldpi ) (~120 dpi).
mdpi منابع صفحه نمایش با چگالی متوسط ​​( mdpi ) (~160 dpi). این چگالی پایه است.
hdpi منابع صفحه نمایش با چگالی بالا ( hdpi ) (~240 dpi).
xhdpi منابع صفحه نمایش با چگالی فوق العاده بالا ( xhdpi ) (~320 dpi).
xxhdpi منابع صفحه نمایش با چگالی فوق العاده بالا ( xxhdpi ) (~480 dpi).
xxxhdpi منابع برای استفاده با چگالی فوق العاده اضافی ( xxxhdpi ) (~640 dpi).
nodpi منابع برای همه تراکم ها اینها منابع مستقل از چگالی هستند. سیستم منابع برچسب گذاری شده با این واجد شرایط را بدون توجه به چگالی صفحه نمایش فعلی مقیاس نمی کند.
tvdpi منابع برای صفحه نمایش جایی بین mdpi و hdpi. تقریبا ~213 نقطه در اینچ. این یک گروه چگالی "اولیه" در نظر گرفته نمی شود. این بیشتر برای تلویزیون ها در نظر گرفته شده است و اکثر برنامه ها به آن نیازی ندارند - ارائه منابع mdpi و hdpi برای اکثر برنامه ها کافی است و سیستم آنها را به اندازه مناسب مقیاس می دهد. اگر نیاز به ارائه منابع tvdpi دارید، اندازه آنها را با ضریب 1.33 * mdpi کنید. به عنوان مثال، یک تصویر 100x100 پیکسل برای صفحه نمایش mdpi، 133x133 پیکسل برای tvdpi است.

برای ایجاد نقشه‌های بیت مپ جایگزین برای چگالی‌های مختلف، از نسبت مقیاس‌بندی 3:4:6:8:12:16 بین شش چگالی اولیه پیروی کنید. به عنوان مثال، اگر یک بیت مپ قابل ترسیم با ابعاد 48x48 پیکسل برای صفحه نمایش های با چگالی متوسط ​​دارید، اندازه ها عبارتند از:

  • 36x36 (0.75x) برای چگالی کم (ldpi)
  • 48x48 (1.0x خط پایه) برای چگالی متوسط ​​(mdpi)
  • 72x72 (1.5x) برای چگالی بالا (hdpi)
  • 96x96 (2.0x) برای چگالی بسیار بالا (xhdpi)
  • 144x144 (3.0x) برای چگالی فوق العاده بالا (xxhdpi)
  • 192x192 (4.0x) برای چگالی فوق العاده فوق العاده بالا (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 قرار دهید

مانند سایر دارایی‌های بیت مپ، باید نسخه‌های مخصوص چگالی نماد برنامه خود را ارائه دهید. با این حال، برخی از راه‌اندازهای برنامه، نماد برنامه شما را تا 25 درصد بزرگ‌تر از آنچه در سطل چگالی دستگاه درخواست می‌شود، نمایش می‌دهند.

به عنوان مثال، اگر سطل تراکم دستگاه 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 ارائه کنید.

برای دستورالعمل‌های طراحی نماد، نمادهای سیستم را ببینید.

برای کمک به ساخت نمادهای برنامه، به ایجاد نمادهای برنامه با Image Asset Studio مراجعه کنید.

توصیه برای مسائل غیر معمول تراکم

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

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

  1. از پیش مقیاس‌گذاری منابع، مانند نقشه‌های بیت‌مپ

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

    اگر ابعاد یک منبع از پیش مقیاس شده را درخواست کنید، سیستم مقادیری را پس از مقیاس بندی نشان دهنده ابعاد برمی گرداند. به عنوان مثال، یک بیت مپ طراحی شده با 50x50 پیکسل برای یک صفحه mdpi به 75x75 پیکسل در یک صفحه hdpi (اگر منبع جایگزینی برای hdpi وجود نداشته باشد) مقیاس می شود و سیستم اندازه را به همین صورت گزارش می کند.

    شرایطی وجود دارد که ممکن است نخواهید اندروید یک منبع را از قبل مقیاس بندی کند. ساده‌ترین راه برای جلوگیری از مقیاس‌گذاری اولیه، قرار دادن منبع در فهرست منبع با واجد شرایط پیکربندی nodpi است. به عنوان مثال:

    res/drawable-nodpi/icon.png

    هنگامی که سیستم از bitmap icon.png از این پوشه استفاده می کند، آن را بر اساس تراکم دستگاه فعلی مقیاس نمی کند.

  2. مقیاس خودکار ابعاد و مختصات پیکسل

    می توانید با تنظیم android:anyDensity روی "false" در مانیفست یا به صورت برنامه ریزی شده برای Bitmap با تنظیم inScaled روی "false" ابعاد و تصاویر پیش مقیاس را غیرفعال کنید. در این مورد، سیستم هر مختصات پیکسل مطلق و مقادیر ابعاد پیکسل را در زمان ترسیم به صورت خودکار مقیاس می کند. این کار را انجام می دهد تا اطمینان حاصل شود که عناصر صفحه نمایش تعریف شده با پیکسل همچنان تقریباً در همان اندازه فیزیکی نمایش داده می شوند که می توانند در تراکم پیکسلی پایه (mdpi) نمایش داده شوند. سیستم این مقیاس را به طور شفاف برای برنامه مدیریت می کند و ابعاد پیکسل های مقیاس شده را به جای ابعاد پیکسل فیزیکی به برنامه گزارش می دهد.

    به عنوان مثال، فرض کنید دستگاهی دارای یک صفحه نمایش با چگالی بالا WVGA است که 480x800 و تقریباً به اندازه یک صفحه نمایش سنتی HVGA است - اما برنامه ای را اجرا می کند که مقیاس اولیه را غیرفعال کرده است. در این حالت، سیستم زمانی که برنامه را برای ابعاد صفحه جستجو می‌کند و 320x533 را گزارش می‌کند، به برنامه دروغ می‌گوید، یعنی ترجمه mdpi تقریبی برای تراکم پیکسل.

    سپس، هنگامی که برنامه عملیات ترسیم را انجام می‌دهد، مانند باطل کردن یک مستطیل از (10،10) به (100،100)، سیستم مختصات را با مقیاس کردن آنها به مقدار مناسب تبدیل می‌کند و در واقع منطقه (15،15) را باطل می‌کند. (150، 150). اگر برنامه شما مستقیماً نقشه بیت مقیاس‌شده را دستکاری کند، ممکن است این اختلاف باعث رفتار غیرمنتظره شود، اما این یک مبادله منطقی برای اطمینان از بهترین عملکرد برنامه ممکن است. اگر با این وضعیت مواجه شدید، تبدیل واحدهای dp به واحدهای پیکسل را بخوانید.

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

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

تست بر روی تمام تراکم پیکسل

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

اگر می‌خواهید روی دستگاه‌های فیزیکی آزمایش کنید اما نمی‌خواهید دستگاه‌ها را بخرید، می‌توانید از Firebase Test Lab برای دسترسی به دستگاه‌های موجود در مرکز داده Google استفاده کنید.