Accessibility Label — این چیست، اساسیات و چگونگی استفاده برای iOS و Android

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

Accessibility Label — اسم عنصر رابطی است که VoiceOver (در iOS) یا TalkBack (در Android) در حالت فکوس آن را بیان می‌کند. در iOS این ویژگی accessibilityLabel و در Android برای عناصری که متن ندارند، contentDescription نامیده می‌شود. به گزارش Apple Developer Documentation, 2024، برچسب اساس دسترسی است: بدون آن، کاربر نمی‌تواند عنصر را شناسایی کند. برچسب باید در حدود یک صفحه منحصر‌به‌فرد باشد و ماهیت عنصر را به زبانی قابل فهم منعکس کند.

نکات کلیدی

  • Accessibility Label — نام عنصری است که خواننده صفحه آن را بیان می‌کند؛ در iOS از طریق accessibilityLabel و در Android از طریق contentDescription تنظیم می‌شود
  • Label باید با متن قابل مشاهده عنصر هماهنگ باشد یا آن را برای مؤلفه‌های غیرمتنی جایگزین کند
  • هر Label در یک صفحه باید منحصر‌به‌فرد باشد — برچسب‌های تکراری کاربر را سرگردان می‌کند
  • لوکالی‌سازی Label اجباری است: برچسب‌ها به تمامی زبان‌های پشتیبانی شده برنامه ترجمه می‌شوند
  • برای کنترل‌های سفارشی، Label از طریق بازنویسی ویژگی یا پروتکل NSObject به‌صورت برنامه‌ای تنظیم می‌شود

Accessibility Label چیست

Accessibility Label یک ویژگی رشته‌ای است که نام عنصر را برای فناوری‌های کمکی تعیین می‌کند. وقتی کاربر در حالی که VoiceOver فعال است انگشت خود را روی صفحه می‌کشد، خواننده صفحه Label عنصری را که فکوس روی آن است می‌خواند. بدون برچسب، کاربر فقط نوع عنصر را می‌شنود: «دکمه»، «تصویر» — بدون ذکر کاربرد.

به گزارش Google I/O 2024, «Accessibility Testing»، 35% از نقض‌های بحرانی دسترسی در برنامه‌های فروشگاهی مربوط به نبود یا نادرستی Label است. Accessibility Scanner در Android نبود برچسب را به عنوان یک خطای با بالاترین شدت آشکار می‌کند.

محدودیت اصلی: Label نباید شامل نوع عنصر باشد. VoiceOver و TalkBack به‌طور خودکار نقش (دکمه، سربرگ، پیوند) را به اعلان اضافه می‌کنند. اگر Label شامل «دکمه ارسال» باشد، کاربر می‌شنود: «دکمه ارسال، دکمه» — تکرار.

Label و WCAG 4.1.2: Name, Role, Value

WCAG 4.1.2 (سطح A) ایجاب می‌کند که هر عنصر رابطی دارای نام (name)، نقش (role) و مقدار (value) قابل تعیین برنامه‌ای باشد. Accessibility Label نام را تامین می‌کند. اگر Label وجود نداشته باشد، معیار نقض شده تلقی می‌شود و برنامه از گواهی اساسی عبور نمی‌کند.

iOS: ویژگی accessibilityLabel

در iOS، accessibilityLabel توسط همه UIView‌ها از پروتکل UIAccessibility به ارث می‌رسد. اگر عنصر حاوی متن باشد (UIButton با title، UILabel با text)، Label به‌طور خودکار بر اساس آن متن تنظیم می‌شود. برای UIImageView، کنترل‌های سفارشی و کانتینرها، Label را باید دستی تنظیم کرد.

مثال برای یک سلول جدول سفارشی:

swift
class CustomTableViewCell: UITableViewCell {
    let titleLabel = UILabel()
    let priceLabel = UILabel()

    override func awakeFromNib() {
        super.awakeFromNib()
        self.isAccessibilityElement = true
        self.accessibilityLabel =
            "\(titleLabel.text ?? "") - \(priceLabel.text ?? "")"
    }
}

برای UIView‌های سفارشی، می‌توان getter accessibilityLabel را بازنویسی کرد:

swift
class RatingView: UIView {
    var rating: Int = 5

    override var accessibilityLabel: String? {
        get { return "امتیاز: \(rating) از 5" }
        set {}
    }
}

Apple HIG, 2024 توصیه می‌کند: اگر عنصر از چند زیرعنصر تشکیل شده است (مثلاً، کارت محصول با نام و قیمت)، آنها را در یک عنصر دسترسی با Label مرکب ترکیب کنید. isAccessibilityElement = true را بر روی والد و false را بر روی فرزندان تنظیم کنید.

NSAttributedString و accessibilityLabel

اگر UILabel از NSAttributedString استفاده کند، accessibilityLabel به‌طور پیش‌فرض برابر با .string (متن ساده) است. اگر نیاز به ارسال مقدار سمانتیکاً متفاوتی داشته باشید (مثلاً، یک ایکون-سمبل که به جای سمبل ★ به عنوان «ستاره» خوانده می‌شود)، accessibilityLabel را به‌صراحت تنظیم کنید. VoiceOver سمبل‌های Unicode را به صورت معنادار نمی‌خواند.

Android: Label از طریق contentDescription

در Android، contentDescription نقش Label را برای ImageView، ImageButton و View‌های سفارشی ایفا می‌کند. برای TextView و Button با متن داخلی، تنظیم contentDescription ضروری نیست — TalkBack متن را به‌طور خودکار می‌خواند.

تنظیم برنامه‌ای از طریق Kotlin:

kotlin
binding.iconStar.contentDescription = "محصول در علاقه‌مندی‌ها"

// برای نمایش سفارشی با چندین عنصر
binding.customCard.setContentDescription(
    "\(title) به مبلغ \(price)")

در XML برای عناصر تزیینی:

xml
<ImageView
    android:contentDescription="@null"
    android:src="@drawable/divider"
    android:importantForAccessibility="no" />

ویژگی importantForAccessibility = "no" عنصر را به‌کلی از درخت دسترسی حذف می‌کند. در iOS، همتای آن isAccessibilityElement = false است.

Compose: semantics و contentDescription

در Jetpack Compose، Label از طریق مودیفیکائر semantics تنظیم می‌شود:

kotlin
Image(
    painter = painterResource(R.drawable.ic_search),
    contentDescription = "جستجوی محصولات",
    modifier = Modifier.semantics {
        contentDescription = "جستجوی محصولات"
    }
)

در Compose، contentDescription یک پارامتر اجباری برای Image است — بدون آن کد ترجیح نمی‌شود (اطلاعیه). این به زور دسترسی را از طریق طراحی API بهبود می‌بخشد.

Label و Hint: تفاوت نقش

Accessibility Label به سوال «این چه عنصری است؛» پاسخ می‌دهد. Hint (accessibilityHint در iOS، متن اضافی در contentDescription در Android) — «در ارتباط چه اتفاقی می‌افتد؛». VoiceOver آنها را به ترتیب بیان می‌کند: ابتدا Label، سپس Hint.

مثال برای دکمه حذف:

  • Label: «حذف»
  • Hint: «عکس انتخاب شده را به‌طور قابل بازگشت حذف می‌کند»
  • VoiceOver: «حذف. عکس انتخاب شده را به‌طور قابل بازگشت حذف می‌کند»

به گزارش Deque University, 2024، جداسازی مناسب Label و Hint نرخ موفقیت انجام وظیفه را برای کاربران VoiceOver تا 28% افزایش می‌دهد. کاربران با اختلالات شناختی به ویژه به Hint وابسته هستند: با خطر فشار دادن روی «حذف» بدون توضیح، 40% از انجام عمل صرف‌نظر می‌کنند.

وقتی Hint لازم نیست

  • عنصر با عمل بدیهی قابل فهم («بازگشت»، «بستن» — Label کافی است)
  • Label از قبل نتیجه را توصیف می‌کند («ارسال پیام» — فعل در خود نام)
  • کنترل‌های سیستمی (UISwitch، UIButton با نوع سیستمی) — رفتار آنها استاندارد است

اشتباهات از تجربه: Label به جای Hint

یک اشتباه رایج: در Label می‌نویسند «دکمه حذف» به جای «حذف». نوع عنصر (دکمه) توسط VoiceOver از طریق trait به‌طور خودکار اضافه می‌شود. در نتیجه، کاربر می‌شنود: «دکمه حذف، دکمه» — تکرار. Label درست: «حذف»، Hint: «عکس انتخاب شده را حذف می‌کند».

لوکالی‌سازی و روش‌های بهتر

لوکالی‌سازی برچسب‌ها اجباری است — از طریق مکانیسم‌های استاندارد انجام می‌شود: NSLocalizedString در iOS، منابع رشته‌ای @string/ در Android. هرگز Label را بدون لوکالی‌سازی با انگلیسی ترکیب نکنید.

قوانین Label خوب، بر اساس W3C WCAG 2.2:

  • با کلمه کلیدی شروع کنید — «جستجوی محصولات»، نه «فیلد جستجوی محصولات»
  • کلمه «دکمه»، «فیلد»، «تصویر» را وارد نکنید — نقش به‌طور خودکار اضافه می‌شود
  • زبان طبیعی قابل فهم برای مخاطب هدف را استفاده کنید
  • از کوتاه‌نویسی‌ها خودداری کنید (جز موارد عمومی: «عد.»، «کگ.») — خواننده صفحه آنها را حرفی می‌خواند
  • برای عناصر ورودی مثال اضافه کنید: «ایمیل (example@domain.com)»

اتصاق Label در چارچوب برند

از واژه‌نامه واحد برای Label در برنامه استفاده کنید. اگر روی یک صفحه «علاقه‌مندی‌ها» و روی صفحه دیگر «نشان‌گذاری‌ها» نوشته شده، کاربر سرگردان می‌شود. یک جدول اصطلاحات دسترسی ایجاد کنید — با طراحان و لوکالی‌سازان هماهنگ کنید.

Label برای عناصر فرم

برای فیلدهای ورودی (UITextField، EditText)، Label باید با placeholder یا عنوان فیلد هماهنگ باشد. اما placeholder معمولاً پس از ورود متن مخفی می‌شود. از accessibilityLabel برای نام ثابت و accessibilityValue برای محتوای فعلی فیلد استفاده کنید — این استاندارد WCAG 4.1.2 است. راه حل: accessibilityLabel را به‌صورت استاتیک (برابر با عنوان فیلد) و accessibilityValue را به‌صورت دینامیک (برابر با متن وارد شده) تنظیم کنید. در iOS این به‌طور خودکار انجام می‌شود، اما برای فیلدهای سفارشی — به صورت دستی از طریق بازنویسی accessibilityValue. بررسی کنید که VoiceOver به جای «، فیلد متنی»، «ایمیل، example@domain.com، فیلد متنی» را بخواند.

چگونگی آزمایش برچسب‌های دسترسی

آزمایش خودکار تنها راه تضمین دقت Label در تمامی صفحات است. iOS XCUIApplication را با دسترسی به .label فراهم می‌کند، Android نیز AccessibilityCheckRule و setContentDescription.

مثال آزمایش برای iOS:

swift
func testLabelsAreUnique() {
    let app = XCUIApplication()
    app.launch()
    let allButtons = app.buttons.allElementsBoundByIndex
    let labels = allButtons.compactMap { $0.label }
    let uniqueLabels = Set(labels)
    XCTAssertEqual(labels.count, uniqueLabels.count,
        "Labelهای تکراری پیدا شد")
}

مثال برای Android با Espresso:

kotlin
@Test
fun testButtonHasAccessibilityLabel() {
    onView(withId(R.id.btnSubmit))
        .check(matches(
            withContentDescription(containsString("ارسال"))
        ))
}

آزمایش دستی: VoiceOver (iOS) یا TalkBack (Android) را فعال کنید و با حرکت انگشت به راست از تمامی عناصر صفحه عبور کنید. هر عنصر باید اعلانی معنادار دریافت کند. اگر فقط «دکمه» یا «تصویر» می‌شنوید — Label وجود ندارد.

روتور VoiceOver و پیمایش سریع

پس از تنظیم Label، کاربر VoiceOver می‌تواند از روتور برای پیمایش سریع استفاده کند: حالات «دکمه‌ها»، «عنوان‌ها»، «پیوندها» و سایر. اگر Label به‌درستی تنظیم شده باشد، VoiceOver عنصر را در حالت روتور مربوطه قرار می‌دهد. بررسی کنید که تمامی دکمه‌ها در حالت «دکمه‌ها» و تمامی عنوان‌ها در حالت «عنوان‌ها» قابل مشاهده هستند.

Label بر جستجوی VoiceOver نیز تأثیر می‌گذارد. کاربر می‌تواند یک کلمه را در حالت جستجو وارد کند و VoiceOver فکوس را به عنصری با Label مناسب منتقل می‌کند. بنابراین، Label باید حاوی کلمات کلیدی باشد که کاربر بر اساس آنها عنصر را جستجو می‌کند.

اتصال به خط لوله CI/CD

بررسی Label را به pipeline اضافه کنید. در iOS از XCUITest با fastlane scan استفاده کنید. در Android از Accessibility Test Framework با قاعده AccessibilityCheckRule که contentDescription خالی را تشخیص می‌دهد، استفاده کنید. این از برگشت‌های در زمان ادغام صفحات جدید جلوگیری می‌کند.

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

تفاوت Accessibility Label با Accessibility Hint چیست؛

Label عنصر را شناسایی می‌کند («جستجو»)، Hint نتیجه عمل را توضیح می‌دهد («صفحه جستجو را باز می‌کند»). VoiceOver Label را بلافاصله در فکوس و Hint را در حالت توضیحات جزئیات بیان می‌کند.

آیا برای UILabel با متن نیاز به تنظیم Label داریم؛

در iOS، UILabel به‌طور خودکار accessibilityLabel مساوی با متن خود را دریافت می‌کند. تنظیم اضافی ضروری نیست. در Android نیز TextView به همین شکل عمل می‌کند.

چگونه Label را برای UIView سفارشی تنظیم کنیم؛

isAccessibilityElement = true را روی View والد تنظیم کنید و accessibilityLabel را بازنویسی کنید تا متن ترکیبی از عناصر فرزند را بازگرداند. برای کامپوننت‌های پیچیده، از ترکیب با جداکننده استفاده کنید.

چگونه از تکرار Label در صفحه جلوگیری کنیم؛

به عناصر تکراری سیاق اضافه کنید: «خرید iPhone 15»، «خرید iPhone 15 Pro». بررسی را از طریق آزمایش‌های UI خودکار کنید — همه Label‌ها را جمع کنید و نبود تکرار را بررسی کنید.

آیا می‌توان از Label برای مخفی‌سازی عنصر از خواننده صفحه استفاده کرد؛

خیر. برای مخفی‌سازی عنصر، از isAccessibilityElement = false در iOS یا importantForAccessibility = "no" در Android استفاده کنید. Label خالی عنصر را مخفی نمی‌کند — خواننده صفحه «بدون نام» را خواهد خواند.

نتیجه‌گیری

  • Accessibility Label — نام عنصر برای VoiceOver و TalkBack؛ در iOS از طریق accessibilityLabel و در Android از طریق contentDescription تنظیم می‌شود
  • Label باید هماهنگ باشد با متن قابل مشاهده عناصر متنی؛ برای غیرمتنی (آیکون‌ها، تصاویر) به صورت دستی تنظیم می‌شود
  • Hint به سوال «چه اتفاقی می‌افتد؛» پاسخ می‌دهد و Label را تکرار نمی‌کند — این ویژگی‌ها نقش‌های متفاوتی دارند
  • هر Label در صفحه باید منحصر‌به‌فرد باشد؛ تکرار کاربر خواننده صفحه را سرگردان می‌کند
  • لوکالی‌سازی برچسب‌ها از طریق NSLocalizedString (iOS) و @string (Android) اجباری است
  • آزمایش کنید Label را به صورت خودکار از طریق آزمایش‌های UI (XCUIApplication، AccessibilityCheckRule) و دستی از طریق VoiceOver
  • عناصر تزیینی را از طریق isAccessibilityElement = false یا importantForAccessibility = "no" مخفی کنید

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

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

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

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