sp: چیست، پیکسل‌های مقیاس‌پذیر برای متن در Android

نویسنده: IT Sectr منتشر شده: 2026-02-25 زمان مطالعه: 9 دقیقه

sp — Scale-independent Pixels، واحد اندازه‌گیری متن در Android که تنظیمات اندازه قلم در دستگاه را در نظر می‌گیرد. برخلاف dp، sp همراه با اندازه قلم سیستم مقیاس‌پذیر می‌شود و دسترسی‌پذیری رابط‌ها را تضمین می‌کند. مقاله تفاوت بین sp و dp را توضیح می‌دهد، تنظیم textSize در XML و Kotlin را نشان می‌دهد و بهترین روش‌های کار با تایپوگرافی در Android را آشکار می‌کند.

موارد کلیدی

  • sp — واحد متن، قابل مقیاس‌پذیری با تنظیمات سیستم قلم کاربر
  • dp — واحد ابعاد عناصر، به تغییر اندازه قلم واکنش نشان نمی‌دهد
  • تفاوت sp و dp: sp = dp × scaleFactor، که scaleFactor به تنظیمات قلم بستگی دارد
  • textSize در XML از طریق sp تنظیم می‌شود: android:textSize="16sp"
  • Material Design گام تایپوگرافی از 12sp تا 34sp را برای عنوان‌ها توصیه می‌کند

sp در Android چیست؟

sp (scale-independent pixel) — واحد اندازه‌گیری اندازه قلم در Android که به طور خودکار با تنظیمات سیستم کاربر مقیاس‌پذیر می‌شود. وقتی مالک دستگاه اندازه قلم را در تنظیمات افزایش می‌دهد، همه عناصر با مقادیر sp به طور متناسب بزرگ می‌شوند. این دسترسی‌پذیری رابط را برای افراد با بینایی ضعیف تضمین می‌کند.

نسبت پایه: 1 sp = 1 dp در مقیاس استاندارد قلم 1.0 (normal). اگر کاربر قلم Large (1.15×) را تنظیم کند، 16 sp به 18.4 پیکسل فیزیکی تبدیل می‌شود. در اندازه قلم Small (0.85×) همان 16 sp برابر 13.6 px خواهد شد. مکانیزم مقیاس‌پذیری از طریق Settings.System.FONT_SCALE در سطح Android Framework مدیریت می‌شود.

طبق Google Material Design Guidelines، متن باید منحصراً با sp تنظیم شود. استثنا — برچسب‌های ثابت در کامپوننت‌هایی که اندازه برای چیدمان حیاتی است (مثلاً متن داخل دکمه‌های با ارتفاع ثابت). در چنین مواردی استفاده از dp با کنترل دستی دسترسی‌پذیری توصیه می‌شود.

sp vs dp: تفاوت‌های کلیدی

تفاوت بین sp و dp — یکی از رایج‌ترین موضوعات سوالات در مصاحبه‌های Android-developer و در code reviewهای واقعی است. هر دو واحد به density-independent pixel وابسته هستند (160 dpi = 1 dp = 1 px در صفحه mdpi)، اما هنگام تغییر اندازه قلم سیستم رفتار متفاوتی دارند.

ویژگیspdp
کاربرداندازه متنابعاد عناصر، فاصله‌ها، عرض، ارتفاع
مقیاس‌پذیری با قلمبله (scale factor)خیر
مقیاس‌پذیری با تراکمبلهبله
API برای تنظیمandroid:textSizeandroid:layout_width, layout_height, padding, margin
Material Design Tokentypescalespacing, sizing

در عمل اشتباه — استفاده از dp برای متن است. اگر متن با dp تنظیم شده باشد، با افزایش قلم مقیاس‌پذیر نمی‌شود و رابط را برای کاربران با بینایی ضعیف غیرقابل دسترس می‌کند. اشتباه معکوس — استفاده از sp برای ارتفاع دکمه یا فاصله‌ها: با افزایش قلم، دکمه ممکن است «باد کند» و چیدمان را خراب کند.

مقیاس‌پذیری sp چگونه کار می‌کند

مقیاس‌پذیری sp در سطح Android Framework در کلاس TypedValue پیاده‌سازی شده است. فرمول تبدیل: sp = dp × scaledDensity، که scaledDensity ضریب مقیاسی است که هم تراکم صفحه و هم تنظیم قلم کاربر را در نظر می‌گیرد.

kotlin
// دریافت برنامه‌نویسی scaledDensity در Kotlin
val scaledDensity = with(context.resources) {
    displayMetrics.scaledDensity
}

// تبدیل sp به px
fun spToPx(sp: Float, context: Context): Float {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_SP,
        sp,
        context.resources.displayMetrics
    )
}

// تبدیل px به sp
fun pxToSp(px: Float, context: Context): Float {
    return px / context.resources.displayMetrics.scaledDensity
}

روش TypedValue.applyDimension — تنها راه صحیح تبدیل sp به پیکسل در runtime است. ضرب مستقیم در scaledDensity کمتر قابل اعتماد است زیرا edge-caseها (مقادیر صفر، سرریز) را مدیریت نمی‌کند. scaledDensity با تغییر تنظیمات قلم از طریق Settings > Display > Font size تغییر می‌کند.

ضرایب مقیاس‌پذیری

Android پنج سطح از پیش تعیین‌شده مقیاس قلم ارائه می‌دهد: Small (0.85×)، Default (1.0×)، Large (1.15×)، Largest (1.3×) و سطح اضافی Very Large (>1.3×) در Android 14+. تولیدکنندگان دستگاه (Samsung، Xiaomi) سطوح خود را اضافه می‌کنند — تا 2.0×. حداقل اندازه متن در sp هرگز تعداد ثابتی پیکسل را تضمین نمی‌کند.

استفاده از sp در XML

در XML sp منحصراً در ویژگی android:textSize استفاده می‌شود. همه اندازه‌های دیگر — width, height, padding, margin, elevation — با dp تنظیم می‌شوند. قانون ساده است: اگر عنصر متن نمایش می‌دهد — اندازه آن در sp، اگر عنصر هندسه را تعریف می‌کند — اندازه در dp.

مثال پایه textSize در XML

xml
<!-- چیدمان TextView با textSize در sp -->
<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    android:textSize="16sp"
    android:padding="12dp"
    android:lineSpacingExtra="4dp" />

<!-- استفاده از منابع dimens -->
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="@dimen/text_body_large" />

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

dimens.xml با tokenهای تایپوگرافی

xml
<!-- res/values/dimens.xml -->
<resources>
    <!-- Material Design Type Scale -->
    <dimen name="text_display_large">34sp</dimen>
    <dimen name="text_display_medium">28sp</dimen>
    <dimen name="text_headline_large">24sp</dimen>
    <dimen name="text_headline_medium">20sp</dimen>
    <dimen name="text_title_large">18sp</dimen>
    <dimen name="text_body_large">16sp</dimen>
    <dimen name="text_body_medium">14sp</dimen>
    <dimen name="text_label_large">14sp</dimen>
    <dimen name="text_label_small">11sp</dimen>
</resources>

Material Design Type Scale شامل 13 سطح اندازه — از 11sp برای برچسب‌های کوچک تا 57sp برای عنوان‌های بزرگ نمایشی است. پروژه‌های Android معمولاً از 8–10 سطح استفاده می‌کنند. همه مقادیر باید مضرب 1sp باشند — مقادیر کسری (15.5sp) به دلیل موقعیت‌یابی زیرپیکسل، رندر را بدتر می‌کنند.

تنظیم تایپوگرافی از طریق Kotlin

در توسعه مدرن Android، متن به ندرت مستقیماً از طریق textSize در sp تنظیم می‌شود. در عوض از سیستم MaterialTheme.typography استفاده می‌شود، جایی که هر سبک از پیش تعریف شده و شامل اندازه، وزن، فاصله بین خطوط و letter-spacing است.

kotlin
// تایپوگرافی سفارشی از طریق Typography API
val AppTypography = Typography(
    displayLarge = TextStyle(
        fontWeight = FontWeight.Normal,
        fontSize = 34.sp,
        lineHeight = 40.sp,
        letterSpacing = 0.sp
    ),
    headlineLarge = TextStyle(
        fontWeight = FontWeight.SemiBold,
        fontSize = 24.sp,
        lineHeight = 32.sp
    ),
    titleLarge = TextStyle(
        fontWeight = FontWeight.Medium,
        fontSize = 18.sp,
        lineHeight = 24.sp
    ),
    bodyLarge = TextStyle(
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp,
        lineHeight = 24.sp,
        letterSpacing = 0.5.sp
    ),
    labelSmall = TextStyle(
        fontWeight = FontWeight.Medium,
        fontSize = 11.sp,
        lineHeight = 16.sp,
        letterSpacing = 0.5.sp
    )
)

تابع گسترش .sp در Jetpack Compose به طور خودکار به scale-independent pixels تبدیل می‌شود. هنگام تغییر اندازه قلم سیستم، Compose fontSize، lineHeight و spacing را مطابق scaledDensity جدید محاسبه می‌کند. TextUnit (کلاس نمایش‌دهنده sp) تضمین می‌کند که متن مقیاس‌پذیر است و فاصله‌ها — خیر.

sp در Jetpack Compose

در Jetpack Compose sp با نوع TextUnit نمایش داده می‌شود که نمی‌تواند به طور تصادفی برای ابعاد عناصر استفاده شود. کامپایلر Kotlin در صورت ارسال TextUnit به جایی که Dp انتظار می‌رود خطا می‌دهد. این کار یک دسته کامل از باگ‌های مرتبط با مقیاس‌پذیری نادرست را از بین می‌برد.

kotlin
// TextUnit در Compose — کار ایمن با sp
@Composable
fun ArticleCard(title: String, description: String) {
    Card(modifier = Modifier
        .fillMaxWidth()
        .padding(16.dp)
    ) {
        Text(
            text = title,
            style = MaterialTheme.typography.titleLarge
        )
        Spacer(modifier = Modifier.height(8.dp))
        Text(
            text = description,
            style = MaterialTheme.typography.bodyMedium
        )
    }
}

// تنظیم صریح fontSize در sp
Text(
    text = "اندازه سفارشی",
    fontSize = 20.sp,
    fontWeight = FontWeight.Bold,
    color = MaterialTheme.colorScheme.primary
)

در Compose معادل مستقیمی برای ویژگی XML android:textSize وجود ندارد — اندازه متن از طریق TextStyle.fontSize تنظیم می‌شود. سیستم MaterialTheme.typography سبک‌های از پیش تعریف شده‌ای ارائه می‌دهد که با Material Design Type Scale مطابقت دارند. اگر اندازه سفارشی نیاز است، از literal 20.sp استفاده می‌شود — زبان تضمین می‌کند که این TextUnit است، نه Dp.

بهترین روش‌های کار با sp

استفاده صحیح از sp — اساس یک برنامه Android قابل دسترس است. در زیر قوانینی بر اساس توصیه‌های Google Material Design و Android Developers Guide جمع‌آوری شده است.

  • همیشه از sp برای متن استفاده کنید — هرگز textSize را با dp یا px تنظیم نکنید، در غیر این صورت کاربران با قلم بزرگ نمی‌توانند رابط را بخوانند
  • از dp برای کانتینرها استفاده کنید — ارتفاع دکمه‌ها، فاصله‌ها و عرض کارت‌ها باید در dp باشد، در غیر این صورت با قلم بزرگ عناصر ممکن است روی هم بیفتند
  • اندازه‌ها را به dimens.xml منتقل کنید — ذخیره متمرکز tokenهای تایپوگرافی refactoring و پشتیبانی از تم تیره را ساده می‌کند
  • از sp کوچکتر از 12sp استفاده نکنید — متن با اندازه کوچکتر در دستگاه‌های با PPI بالا و با قلم استاندارد غیرقابل خواندن می‌شود
  • در حداکثر مقیاس قلم تست کنید — در تنظیمات دستگاه بزرگترین قلم را فعال کنید و بررسی کنید که رابط خراب نمی‌شود

قانون اصلی دسترسی‌پذیری: کاربر باید بتواند قلم را بدون از دست دادن عملکرد افزایش دهد. اگر برنامه در مقیاس قلم 1.3× به درستی کار کند، تست‌های پایه accessibility را پشت سر می‌گذارد. Google Play ممکن است برنامه را رد کند اگر textSize با dp تنظیم شده باشد و رابط مقیاس‌پذیر نباشد.

سوالات متداول

sp چه تفاوتی با dp دارد؟

sp (scale-independent pixel) با تغییر اندازه سیستم قلم مقیاس‌پذیر می‌شود، اما dp — خیر. sp فقط برای متن استفاده می‌شود، dp — برای همه اندازه‌های دیگر عناصر. ضریب تبدیل: sp = dp × FONT_SCALE.

آیا می‌توان از sp برای فاصله‌ها استفاده کرد؟

خیر. فاصله‌ها، ارتفاع دکمه‌ها، عرض کارت‌ها باید با dp تنظیم شوند. استفاده از sp برای فاصله‌ها باعث می‌شود که با افزایش قلم، عناصر به طور غیرطبیعی بزرگ شوند و ممکن است از مرزهای صفحه خارج شوند.

چگونه بررسی کنیم که برنامه با sp به درستی کار می‌کند؟

Settings > Display > Font size را باز کنید و حداکثر مقدار (Largest) را تنظیم کنید. برنامه را اجرا کنید و بررسی کنید که همه متن خوانا است، عناصر روی هم نمی‌افتند و دکمه‌ها از مرزهای صفحه خارج نمی‌شوند. برای خودکارسازی از Espresso با UiAutomator استفاده کنید.

حداقل اندازه مجاز متن در sp چقدر است؟

Material Design حداقل اندازه 11sp را برای labelSmall توصیه می‌کند. برای متن اصلی — از 14sp (bodyMedium) تا 16sp (bodyLarge). اندازه‌های کوچکتر از 11sp توصیه نمی‌شوند زیرا در دستگاه‌های با تراکم پیکسل بالا غیرقابل خواندن می‌شوند.

اگر textSize را با dp تنظیم کنم چه اتفاقی می‌افتد؟

متن در اندازه ثابت بدون توجه به تنظیمات سیستم قلم نمایش داده می‌شود. کاربران با قلم بزرگ نمی‌توانند راحت چنین متنی را بخوانند. این نیازهای دسترسی‌پذیری WCAG را نقض می‌کند و می‌تواند دلیل رد برنامه در Google Play شود.

خلاصه

  • sp — واحد اندازه‌گیری قلم در Android، قابل مقیاس‌پذیری با تنظیمات کاربر از طریق FONT_SCALE
  • dp — واحد برای ابعاد عناصر، بدون واکنش به تغییر اندازه قلم
  • textSize در XML از طریق android:textSize="16sp" تنظیم می‌شود، همه اندازه‌های دیگر — در dp
  • MaterialTheme.typography در Jetpack Compose از TextUnit (.sp) برای ایمنی نوع استفاده می‌کند
  • dimens.xml — ذخیره متمرکز tokenهای تایپوگرافی برای یکپارچگی
  • حداقل اندازه متن — 11sp، توصیه شده برای body — 14–16sp
  • تست در حداکثر مقیاس قلم — مرحله اجباری بررسی دسترسی‌پذیری

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید