توضّح هذه الصفحة كيفية ضبط الخطوط في تطبيق Compose.
ضبط الخط
تحتوي الدالة Text على مَعلمة fontFamily للسماح بضبط الخط المستخدَم في الدالة المركّبة. يتم تلقائيًا تضمين مجموعات الخطوط serif وsans-serif وmonospace وcursive:
@Composable fun DifferentFonts() { Column { Text("Hello World", fontFamily = FontFamily.Serif) Text("Hello World", fontFamily = FontFamily.SansSerif) } }
يمكنك استخدام السمة fontFamily للتعامل مع الخطوط المخصّصة والمحارف المحدّدة في المجلد res/font:
يوضّح هذا المثال كيفية تحديد fontFamily استنادًا إلى ملفات الخطوط هذه وباستخدام الدالة Font:
val firaSansFamily = FontFamily( Font(R.font.firasans_light, FontWeight.Light), Font(R.font.firasans_regular, FontWeight.Normal), Font(R.font.firasans_italic, FontWeight.Normal, FontStyle.Italic), Font(R.font.firasans_medium, FontWeight.Medium), Font(R.font.firasans_bold, FontWeight.Bold) )
يمكنك تمرير هذه السمة fontFamily إلى الدالة المركّبة Text. بما أنّ fontFamily يمكن أن يتضمّن أوزانًا مختلفة، يمكنك ضبط fontWeight يدويًا لاختيار الوزن المناسب للنص:
Column { Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Light) Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Normal) Text( text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Normal, fontStyle = FontStyle.Italic ) Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Medium) Text(text = "text", fontFamily = firaSansFamily, fontWeight = FontWeight.Bold) }
للتعرّف على كيفية ضبط أسلوب الخط في تطبيقك بالكامل، يُرجى الاطّلاع على أنظمة التصميم المخصّصة في Compose.
الخطوط القابلة للتنزيل
بدءًا من الإصدار 1.2.0 من Compose، يمكنك استخدام واجهة برمجة التطبيقات للخطوط القابلة للتنزيل في تطبيق Compose لتنزيل خطوط Google بشكل غير متزامن واستخدامها في تطبيقك.
لا يتوفّر حاليًا دعم للخطوط القابلة للتنزيل التي يوفّرها مقدّمو الخدمات المخصّصة.
استخدام الخطوط القابلة للتنزيل آليًا
لتنزيل خط برمجيًا من داخل تطبيقك، اتّبِع الخطوات التالية:
- أضِف التبعية:
أنيق
dependencies { ... implementation "androidx.compose.ui:ui-text-google-fonts:1.12.1" }
Kotlin
dependencies { ... implementation("androidx.compose.ui:ui-text-google-fonts:1.12.1") }
- ابدأ تشغيل
GoogleFont.Providerباستخدام بيانات اعتماد Google Fonts: المَعلمات التي يتلقّاها مقدّم الخدمة هي:val provider = GoogleFont.Provider( providerAuthority = "com.google.android.gms.fonts", providerPackage = "com.google.android.gms", certificates = R.array.com_google_android_gms_fonts_certs )
- تمثّل هذه السياسة مرجع موفّر الخطوط في Google Fonts.
- حزمة موفّر الخطوط لإثبات هوية الموفّر
- قائمة بمجموعات من تجزئات الشهادات للتحقّق من هوية
مقدّم الخدمة. يمكنك العثور على التجزئات المطلوبة لموفّر Google Fonts
في ملف
font_certs.xmlفي نموذج تطبيق Jetchat.
- تحديد
FontFamily: يمكنك الاستعلام عن مَعلمات أخرى للخط، مثل السُمك والنمط، باستخدام// ... import androidx.compose.ui.text.googlefonts.GoogleFont import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.googlefonts.Font // ... val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font(googleFont = fontName, fontProvider = provider) )
FontWeightوFontStyleعلى التوالي:// ... import androidx.compose.ui.text.googlefonts.GoogleFont import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.googlefonts.Font // ... val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font( googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold, style = FontStyle.Italic ) )
- اضبط
FontFamilyلاستخدامه في الدالة المركّبة Text:
Text( fontFamily = fontFamily, text = "Hello World!" )
يمكنك أيضًا تحديد
الخطوط لاستخدام
FontFamily:
val MyTypography = Typography( bodyMedium = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = 12.sp/*...*/ ), bodyLarge = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.Bold, letterSpacing = 2.sp, /*...*/ ), headlineMedium = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.SemiBold/*...*/ ), /*...*/ )
بعد ذلك، اضبط "أسلوب الخط" (Typography) على مظهر تطبيقك:
MyAppTheme( typography = MyTypography )/*...*/
للاطّلاع على مثال لتطبيق يستخدم الخطوط القابلة للتنزيل في Compose مع Material3، يمكنك الاطّلاع على نموذج تطبيق Jetchat.
إضافة خطوط احتياطية
يمكنك تحديد سلسلة من الخطوط الاحتياطية لخطك في حالة فشل تنزيل الخط بشكل صحيح. على سبيل المثال، إذا كان لديك خط قابل للتنزيل محدّد على النحو التالي:
// ... import androidx.compose.ui.text.googlefonts.Font // ... val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font(googleFont = fontName, fontProvider = provider), Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold) )
يمكنك تحديد الإعدادات التلقائية للخط لكل من السُمكين على النحو التالي:
// ... import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.googlefonts.Font // ... val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font(googleFont = fontName, fontProvider = provider), Font(resId = R.font.my_font_regular), Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold), Font(resId = R.font.my_font_regular_bold, weight = FontWeight.Bold) )
تأكَّد من إضافة عمليات الاستيراد الصحيحة.
يؤدي تحديد FontFamily بهذه الطريقة إلى إنشاء FontFamily يحتوي على سلسلتين،
واحدة لكل وزن. ستحاول آلية التحميل حلّ مشكلة الخط على الإنترنت أولاً،
ثم الخط الموجود في مجلد موارد R.font المحلي.
تصحيح أخطاء عملية التنفيذ
للمساعدة في التحقّق من تنزيل الخط بشكل صحيح، يمكنك تحديد معالج دالة coroutine لتصحيح الأخطاء. يوفّر المعالج سلوك ما يجب فعله في حالة فشل تحميل الخط بشكل غير متزامن.
ابدأ بإنشاء
CoroutineExceptionHandler:
val handler = CoroutineExceptionHandler { _, throwable -> // process the Throwable Log.e(TAG, "There has been an issue: ", throwable) }
مرِّرها إلى الطريقة
createFontFamilyResolver
ليستخدم المحلِّل المعالج الجديد:
CompositionLocalProvider( LocalFontFamilyResolver provides createFontFamilyResolver(LocalContext.current, handler) ) { Column { Text( text = "Hello World!", style = MaterialTheme.typography.bodyMedium ) } }
يمكنك أيضًا استخدام واجهة برمجة التطبيقات
isAvailableOnDevice
من الموفِّر لاختبار ما إذا كان الموفِّر متاحًا وتم ضبط الشهادات
بشكل صحيح. لإجراء ذلك، يمكنك استدعاء طريقة isAvailableOnDevice
التي تعرض القيمة "خطأ" إذا تم ضبط الموفّر بشكل غير صحيح.
val context = LocalContext.current LaunchedEffect(Unit) { if (provider.isAvailableOnDevice(context)) { Log.d(TAG, "Success!") } }
المحاذير
يستغرق Google Fonts عدة أشهر لإتاحة الخطوط الجديدة على Android.
هناك فارق زمني بين وقت إضافة خط في fonts.google.com ووقت توفّره من خلال واجهة برمجة التطبيقات للخطوط القابلة للتنزيل (إما في نظام العرض أو في Compose). قد يتعذّر تحميل الخطوط المُضافة حديثًا في تطبيقك مع ظهور الخطأ IllegalStateException.
لمساعدة المطوّرين في تحديد هذا الخطأ من بين الأنواع الأخرى من أخطاء تحميل الخطوط،
أضفنا رسائل وصفية للاستثناء في Compose مع التغييرات
الموضّحة هنا.
إذا واجهت أي مشاكل، يُرجى الإبلاغ عنها باستخدام أداة تتبُّع المشاكل.
استخدام الخطوط المتغيّرة
الخط المتغيّر هو تنسيق خط يسمح لملف خط واحد باحتواء أنماط مختلفة. باستخدام الخطوط المتغيّرة، يمكنك تعديل المحاور (أو المَعلمات) لإنشاء النمط المفضّل لديك. يمكن أن تكون هذه المحاور عادية، مثل الوزن والعرض والميل والخط المائل، أو مخصّصة، وتختلف باختلاف الخطوط المتغيّرة.
يتيح لك استخدام الخطوط المتغيّرة بدلاً من ملفات الخطوط العادية الحصول على ملف خط واحد فقط بدلاً من ملفات متعددة.
لمزيد من المعلومات حول الخطوط المتغيّرة، يُرجى الاطّلاع على Google Fonts Knowledge والكتالوج الكامل للخطوط المتغيّرة المتاحة وجدول المحاور المتوافقة لكل خط.
يوضّح لك هذا المستند كيفية تنفيذ خط متغيّر في تطبيق Compose.
تحميل خط متغيّر
نزِّل الخط المتغيّر الذي تريد استخدامه (على سبيل المثال، Roboto Flex) وضَعه في المجلد
app/res/fontفي تطبيقك. تأكَّد من أنّأنّ ملفttfالذي تضيفه هو إصدار الخط المتغيّر للخط، وأنّ اسم ملف الخط مكتوب بأحرف صغيرة ولا يحتوي على أي رموز خاصة.لتحميل خط متغيّر، حدِّد
FontFamilyباستخدام الخط الموضوع في دليلres/font/:// In Typography.kt @OptIn(ExperimentalTextApi::class) val displayLargeFontFamily = FontFamily( Font( R.font.robotoflex_variable, variationSettings = FontVariation.Settings( FontVariation.weight(950), FontVariation.width(30f), FontVariation.slant(-6f), ) ) )
تتيح لك واجهة برمجة التطبيقات
FontVariationضبط محاور الخطوط العادية، مثل الوزن والعرض والميل. هذه هي المحاور القياسية المتوفرة مع أي خط متغير. يمكنك إنشاء تكوينات مختلفة للخط بناءً على مكان استخدام الخط.لا تتوفّر الخطوط المتغيّرة إلا في الإصدار Android O والإصدارات الأحدث، لذا أضِف حاجز حماية واضبط خيارًا احتياطيًا مناسبًا:
// In Typography.kt val default = FontFamily( /* * This can be any font that makes sense */ Font( R.font.robotoflex_static_regular ) ) @OptIn(ExperimentalTextApi::class) val displayLargeFontFamily = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { FontFamily( Font( R.font.robotoflex_variable, variationSettings = FontVariation.Settings( FontVariation.weight(950), FontVariation.width(30f), FontVariation.slant(-6f), ) ) ) } else { default }
استخرِج الإعدادات في مجموعة من الثوابت لتسهيل إعادة استخدامها واستبدال إعدادات الخط بهذه الثوابت:
// VariableFontDimension.kt object DisplayLargeVFConfig { const val WEIGHT = 950 const val WIDTH = 30f const val SLANT = -6f const val ASCENDER_HEIGHT = 800f const val COUNTER_WIDTH = 500 } @OptIn(ExperimentalTextApi::class) val displayLargeFontFamily = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { FontFamily( Font( R.font.robotoflex_variable, variationSettings = FontVariation.Settings( FontVariation.weight(DisplayLargeVFConfig.WEIGHT), FontVariation.width(DisplayLargeVFConfig.WIDTH), FontVariation.slant(DisplayLargeVFConfig.SLANT), ) ) ) } else { default }
اضبط أسلوب الخط في التصميم المتعدد الأبعاد 3 لاستخدام
FontFamily:// Type.kt val Typography = Typography( displayLarge = TextStyle( fontFamily = displayLargeFontFamily, fontSize = 50.sp, lineHeight = 64.sp, letterSpacing = 0.sp, /***/ ) )
يستخدم هذا النموذج
displayLargeأسلوب الخطوط في Material 3، والذي يتضمّن إعدادات مختلفة للخطوط التلقائية والاستخدامات المقترَحة. على سبيل المثال، يجب استخدامdisplayLargeللنصوص القصيرة والمهمة، لأنّه أكبر نص على الشاشة.باستخدام Material 3، يمكنك تغيير القيم التلقائية لـ
TextStyleوfontFamilyلتخصيص أسلوب الخط. في المقتطف أعلاه، يمكنك ضبط مثيلاتTextStyleلتخصيص إعدادات الخط لكل مجموعة خطوط.بعد تحديد أسلوب الخط، يمكنك تمريره إلى M3
MaterialTheme:MaterialTheme( colorScheme = MaterialTheme.colorScheme, typography = Typography, content = content )
أخيرًا، استخدِم دالة
Textمركّبة وحدِّد النمط على أحد أنماط الخطوط المحدّدة،MaterialTheme.typography.displayLarge:@Composable @Preview fun CardDetails() { MyCustomTheme { Card( shape = RoundedCornerShape(8.dp), elevation = CardDefaults.cardElevation(defaultElevation = 4.dp), modifier = Modifier .fillMaxWidth() .padding(16.dp) ) { Column( modifier = Modifier.padding(16.dp) ) { Text( text = "Compose", style = MaterialTheme.typography.displayLarge, modifier = Modifier.padding(bottom = 8.dp), maxLines = 1 ) Text( text = "Beautiful UIs on Android", style = MaterialTheme.typography.headlineMedium, modifier = Modifier.padding(bottom = 8.dp), maxLines = 2 ) Text( text = "Jetpack Compose is Android’s recommended modern toolkit for building native UI. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.", style = MaterialTheme.typography.bodyLarge, modifier = Modifier.padding(bottom = 8.dp), maxLines = 3 ) } } } }
يتم ضبط كل دالة مركّبة من
Textمن خلال نمط تخصيص التصميم المتعدد الأبعاد، وتحتوي على إعدادات مختلفة للخطوط المتغيّرة. يمكنك استخدامMaterialTheme.typographyلاسترداد أسلوب الخط المقدَّم إلى الدالة المركّبةMaterialThemeفي M3.
استخدام محاور مخصّصة
يمكن أن تحتوي الخطوط أيضًا على محاور مخصّصة. ويتم تحديدها ضمن ملف الخط نفسه.
على سبيل المثال، يتضمّن خط Roboto Flex محور ارتفاع الجزء الصاعد ("YTAS") الذي يضبط ارتفاع الأجزاء الصاعدة في الأحرف الصغيرة، بينما يضبط عرض الفراغ الداخلي ("XTRA") عرض كل حرف.
يمكنك تغيير قيمة هذه المحاور من خلال إعدادات FontVariation.
لمزيد من المعلومات حول المحاور المخصّصة التي يمكنك ضبطها لخط معيّن، يُرجى الاطّلاع على جدول المحاور المتوافقة لكل خط.
لاستخدام المحاور المخصّصة، حدِّد دوالّ للمحورَين المخصّصَين
ascenderHeightوcounterWidth:fun ascenderHeight(ascenderHeight: Float): FontVariation.Setting { require(ascenderHeight in 649f..854f) { "'Ascender Height' must be in 649f..854f" } return FontVariation.Setting("YTAS", ascenderHeight) } fun counterWidth(counterWidth: Int): FontVariation.Setting { require(counterWidth in 323..603) { "'Counter width' must be in 323..603" } return FontVariation.Setting("XTRA", counterWidth.toFloat()) }
تؤدي هذه الدوالّ ما يلي:
- حدِّد قيودًا للقيم التي يمكن قبولها. كما ترى في
دليل الخطوط المتغيّرة، الحد الأدنى لقيمة
ascenderHeight (YTAS)هو649fوالحد الأقصى هو854f. - أعِد إعداد الخط، حتى يصبح الإعداد جاهزًا للإضافة إلى الخط. في طريقة
FontVariation.Setting()، يتم ترميز اسم المحور (YTAS, XTRA) بشكل ثابت، ويتم استخدام القيمة كمَعلمة.
- حدِّد قيودًا للقيم التي يمكن قبولها. كما ترى في
دليل الخطوط المتغيّرة، الحد الأدنى لقيمة
باستخدام المحاور مع إعدادات الخط، يمكنك تمرير مَعلمات إضافية إلى كل
Fontيتم تحميله:@OptIn(ExperimentalTextApi::class) val displayLargeFontFamily = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { FontFamily( Font( R.font.robotoflex_variable, variationSettings = FontVariation.Settings( FontVariation.weight(DisplayLargeVFConfig.WEIGHT), FontVariation.width(DisplayLargeVFConfig.WIDTH), FontVariation.slant(DisplayLargeVFConfig.SLANT), ascenderHeight(DisplayLargeVFConfig.ASCENDER_HEIGHT), counterWidth(DisplayLargeVFConfig.COUNTER_WIDTH) ) ) ) } else { default }
لاحظ أنّ ارتفاع الحروف الصاعدة الصغيرة قد زاد الآن، وأنّ النص الآخر أصبح أوسع:
مراجع إضافية
لمزيد من المعلومات، يُرجى الاطّلاع على منشور المدوّنة التالي حول الخطوط المتغيّرة:
التطبيقات المقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما يكون JavaScript غير مفعَّل
- الموارد في Compose
- تنسيق النص
- التصميم المتعدد الأبعاد 2 في Compose