از محتوای مقیاس‌پذیر کاربر پشتیبانی کنید

برای پشتیبانی از محتوای مقیاس‌پذیر در برنامه‌تان، اشاره‌های نزدیک کردن انگشتان برای بزرگ‌نمایی را پیاده‌سازی کنید. این روش استاندارد و سازگار با پلاتفرم برای بهبود دسترس‌پذیری است، که به کاربران اجازه می‌دهد به‌طور شهودی اندازه نوشتار و عناصر میانای کاربر را متناسب با نیازهایشان تنظیم کنند. برنامه شما می‌تواند رفتار مقیاس‌بندی سفارشی را با کنترل دانه‌ای و رفتار زمینه‌ای تعریف کند که تجربه‌ای را ارائه می‌دهد که کاربران اغلب سریع‌تر از ویژگی سطح سیستم مانند بزرگ‌نمایی صفحه کشف می‌کنند.

انتخاب استراتژی مقیاس‌بندی

استراتژی‌های پوشش‌داده‌شده در این راهنما باعث می‌شود واسط کاربر برای مطابقت با عرض صفحه‌نمایش، بازآرایی و بازسازماندهی شود. این کار مزیت دسترس‌پذیری قابل‌توجهی را با حذف نیاز به حرکت افقی و حرکت ناامیدکننده «زیگزاگ» فراهم می‌کند که درغیراین‌صورت برای خواندن خطوط طولانی نوشتار لازم است.

مطالعه بیشتر: تحقیقات تأیید می‌کند که برای کاربران کم‌بینا، محتوای بازآرایی‌شده به‌طور قابل‌توجهی خواناتر است و پیمایش آن نسبت‌به رابط‌هایی که به حرکت افقی دوبعدی نیاز دارند آسان‌تر است. برای جزئیات بیشتر، مقایسه محتوای Pan-and-Scan و Reflowable در دستگاه‌های همراه را ببینید.

مقیاس‌بندی همه عناصر یا فقط عناصر نوشتاری

جدول زیر تأثیر بصری هر استراتژی مقیاس‌بندی را نشان می‌دهد.

استراتژی مقیاس‌بندی تراکم مقیاس‌بندی قلم

رفتار

همه چیز را به‌طور متناسب مقیاس‌بندی می‌کند. محتوا برای قرار گرفتن در ظرف خود بازچینی می‌شود، بنابراین کاربر برای دیدن کل محتوا نیازی به حرکت افقی ندارد.

فقط بر عناصر نوشتاری تأثیر می‌گذارد. چیدمان کلی و مؤلفه‌های غیرنوشتاری در همان اندازه باقی می‌مانند.

What Scales

همه عناصر دیداری: نوشتار، مؤلفه‌ها (دکمه‌ها، نمادها)، تصاویر، و فاصله‌گذاری چیدمان (حاشیه داخلی، حاشیه خارجی)

فقط نوشتار

نمایش

توصیه‌ها

اکنون که تفاوت‌های دیداری را دیده‌اید، جدول زیر به شما کمک می‌کند تا موازنه‌ها را بسنجید و بهترین استراتژی را برای محتوای خود انتخاب کنید.

نوع میانای کاربر

راهبرد توصیه‌شده

استدلال

چیدمان‌های مناسب برای خواندن زیاد

مثال: مقاله‌های خبری، برنامه‌های پیام‌رسانی

تراکم یا مقیاس‌بندی قلم

مقیاس‌بندی تراکم برای مقیاس‌بندی کل ناحیه محتوا، ازجمله تصاویر درون‌خطی، ترجیح داده می‌شود.

اگر فقط نوشتار نیاز به مقیاس‌بندی داشته باشد، مقیاس‌بندی قلم جایگزین ساده‌ای است.

چیدمان‌های ساختاریافته بصری

مثال‌ها: فروشگاه‌های برنامه، فیدهای رسانه‌های اجتماعی

مقیاس‌بندی تراکم

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

تشخیص اشاره‌های مقیاس‌بندی در Jetpack Compose

برای پشتیبانی از محتوای مقیاس‌پذیر توسط کاربر، ابتدا باید اشاره‌های چندلمسی را شناسایی کنید. در Jetpack Compose، می‌توانید این کار را بااستفاده از Modifier.transformable انجام دهید.

اصلاح‌کننده transformable یک API سطح بالا است که دلتا را از آخرین رویداد اشاره ارائه می‌دهد.zoomChange این کار منطق به‌روزرسانی وضعیت را به انباشت مستقیم (برای مثال، scale *= zoomChange) ساده می‌کند و آن را برای راهبردهای مقیاس‌بندی تطبیقی که در این راهنما پوشش داده شده است ایده‌آل می‌کند.

پیاده‌سازی‌های نمونه

مثال‌های زیر نحوه پیاده‌سازی استراتژی‌های مقیاس‌بندی تراکم و مقیاس‌بندی قلم را نشان می‌دهد.

مقیاس‌بندی تراکم

این رویکرد density پایه ناحیه واسط کاربر را مقیاس‌بندی می‌کند. درنتیجه، همه اندازه‌گیری‌های مبتنی بر چیدمان (ازجمله حاشیه داخلی، فاصله‌گذاری، و اندازه‌های مؤلفه) مقیاس‌بندی می‌شوند، گویی اندازه یا وضوح صفحه‌نمایش تغییر کرده است. چون اندازه نوشتار به تراکم نیز بستگی دارد، به‌طور متناسب مقیاس‌بندی می‌شود. این استراتژی زمانی مؤثر است که بخواهید همه عناصر را به‌طور یکنواخت در یک ناحیه خاص بزرگ کنید و ریتم بصری کلی و نسبت‌های واسط کاربر را حفظ کنید.

private class DensityScalingState(
    // Note: For accessibility, typical min/max values are ~0.75x and ~3.5x.
    private val minScale: Float = 0.75f,
    private val maxScale: Float = 3.5f,
    private val currentDensity: Density
) {
    val transformableState = TransformableState { zoomChange, _, _ ->
        scaleFactor.floatValue =
            (scaleFactor.floatValue * zoomChange).coerceIn(minScale, maxScale)
    }
    val scaleFactor = mutableFloatStateOf(1f)
    fun scaledDensity(): Density {
        return Density(
            currentDensity.density * scaleFactor.floatValue,
            currentDensity.fontScale
        )
    }
}

@Composable
fun DensityScalingSample() {
    val currentDensity = LocalDensity.current
    val scaleState =
        remember(currentDensity) { DensityScalingState(currentDensity = currentDensity) }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .transformable(state = scaleState.transformableState),
        contentAlignment = Alignment.TopCenter
    ) {
        CompositionLocalProvider(
            LocalDensity provides scaleState.scaledDensity()
        ) {
            DemoCard()
        }
    }
}

مقیاس‌بندی قلم

این استراتژی هدفمندتر است و فقط عامل fontScale را تغییر می‌دهد. نتیجه این است که فقط عناصر نوشتاری بزرگ یا کوچک می‌شوند، درحالی‌که همه مؤلفه‌های چیدمان دیگر (مانند محفظه‌ها، حاشیه‌گذاری، و نمادها) در اندازه ثابت باقی می‌مانند. این استراتژی برای بهبود خوانایی نوشتار در برنامه‌هایی که خواندن در آن‌ها زیاد است بسیار مناسب است.

class FontScaleState(
    // Note: For accessibility, typical min/max values are ~0.75x and ~3.5x.
    private val minScale: Float = 0.75f,
    private val maxScale: Float = 3.5f,
    private val currentDensity: Density
) {
    val transformableState = TransformableState { zoomChange, _, _ ->
        scaleFactor.floatValue =
            (scaleFactor.floatValue * zoomChange).coerceIn(minScale, maxScale)
    }
    val scaleFactor = mutableFloatStateOf(1f)
    fun scaledFont(): Density {
        return Density(
            currentDensity.density,
            currentDensity.fontScale * scaleFactor.floatValue
        )
    }
}

@Composable
fun FontScalingSample() {
    val currentDensity = LocalDensity.current
    val scaleState = remember { FontScaleState(currentDensity = currentDensity) }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .transformable(state = scaleState.transformableState),
        contentAlignment = Alignment.TopCenter
    ) {
        CompositionLocalProvider(
            LocalDensity provides scaleState.scaledFont()
        ) {
            DemoCard()
        }
    }
}

واسط کاربر نمایشی هم‌رسانی‌شده

این DemoCard ترکیب‌پذیر مشترک است که توسط هر دو مثال قبلی استفاده می‌شود تا رفتارهای مختلف مقیاس‌بندی را برجسته کند.

@Composable
private fun DemoCard() {
    Card(
        modifier = Modifier
            .width(360.dp)
            .padding(16.dp),
        shape = RoundedCornerShape(12.dp)
    ) {
        Column(
            modifier = Modifier.padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            Text("Demo Card", style = MaterialTheme.typography.headlineMedium)
            var isChecked by remember { mutableStateOf(true) }
            Row(verticalAlignment = Alignment.CenterVertically) {
                Text("Demo Switch", Modifier.weight(1f), style = MaterialTheme.typography.bodyLarge)
                Switch(checked = isChecked, onCheckedChange = { isChecked = it })
            }
            Row(verticalAlignment = Alignment.CenterVertically) {
                Icon(Icons.Filled.Person, "Icon", Modifier.size(32.dp))
                Spacer(Modifier.width(8.dp))
                Text("Demo Icon", style = MaterialTheme.typography.bodyLarge)
            }
            Row(
                Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween
            ) {
                Box(
                    Modifier
                        .width(100.dp)
                        .weight(1f)
                        .height(80.dp)
                        .background(Color.Blue)
                )
                Box(
                    Modifier
                        .width(100.dp)
                        .weight(1f)
                        .height(80.dp)
                        .background(Color.Red)
                )
            }
            Text(
                "Demo Text: Lorem ipsum dolor sit amet, consectetur adipiscing elit," +
                    " sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
                style = MaterialTheme.typography.bodyMedium,
                textAlign = TextAlign.Justify
            )
        }
    }
}

نکته‌ها و ملاحظات

برای ایجاد تجربه‌ای بی‌نقص‌تر و دردسترس‌تر، توصیه‌های زیر را درنظر بگیرید:

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