توضح هذه الصفحة كيفية ضبط الخطوط في تطبيق Compose.
ضبط الخط
تتضمن السمة Text
المعلَمة fontFamily
للسماح بضبط الخط المستخدَم في العنصر القابل للإنشاء. بشكل افتراضي، يتم تضمين مجموعات الخطوط serif وsans-serif وsolarmora وعائلات الخطوط التدوينية:
@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.
الخطوط القابلة للتنزيل
بدءًا من Compose 1.2.0، يمكنك استخدام واجهة Font API القابلة للتنزيل في تطبيق Compose لتنزيل خطوط Google بشكل غير متزامن واستخدامها في تطبيقك.
لا يتوفر حاليًا دعم الخطوط القابلة للتنزيل التي يوفرها مزوّدو الخدمة المخصصون.
استخدام الخطوط القابلة للتنزيل آليًا
لتنزيل خط آليًا من داخل تطبيقك، اتّبع الخطوات التالية:
- أضف التبعية:
رائع
dependencies { ... implementation "androidx.compose.ui:ui-text-google-fonts:1.6.8" }
Kotlin
dependencies { ... implementation("androidx.compose.ui:ui-text-google-fonts:1.6.8") }
- عليك إعداد
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.
- حزمة موفر الخط للتحقق من هوية الموفر.
- تمثّل هذه السمة قائمة بمجموعات علامات التجزئة للشهادات بهدف إثبات هوية الموفّر. يمكنك العثور على علامات التجزئة المطلوبة لموفّر خطوط Google
في ملف
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( fontFamily = fontFamily, text = "Hello World!" )
يمكنك أيضًا تحديد أسلوب الخط لاستخدام FontFamily
:
val MyTypography = Typography( labelMedium = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = 12.sp/*...*/ ), labelLarge = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.Bold, letterSpacing = 2.sp, /*...*/ ), displayMedium = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.SemiBold/*...*/ ), /*...*/ )
بعد ذلك، اضبط أسلوب الخط على موضوع تطبيقك:
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
على الجهاز.
تصحيح أخطاء عملية التنفيذ
لمساعدتك في التحقّق مما إذا تم تنزيل الخط بشكل صحيح، يمكنك تحديد معالج تصحيح أخطاء الكوروتين. يوفر الاسم المعرِّف سلوك ما يجب فعله في حال فشل تحميل الخط بشكل غير متزامن.
ابدأ بإنشاء
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
التي تعرض القيمة false إذا تم إعداد موفِّر الخدمة بشكل غير صحيح.
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
ضبط محاور الخط العادية، مثل weight وwidth وSlant. هذه محاور قياسية متوفرة بأي خط متغير. يمكنك إنشاء تكوينات مختلفة للخط بناءً على المكان الذي سيتم استخدام الخط فيه.لا تتوفّر الخطوط المتغيّرة إلا للإصدارات O والإصدارات الأحدث من Android، لذا أضِف حاجزًا واضبُط إجراء احتياطي مناسب:
// 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 }
اضبط أسلوب الخط في Material Design 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
لتخصيص إعدادات الخطوط لكل مجموعة خطوط.الآن بعد أن حددت أسلوب الخط، عليك تمريره إلى
MaterialTheme
M3: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
لاسترداد أسلوب الخط المقدَّم في العنصر القابل للإنشاء M3MaterialTheme
.
استخدام محاور مخصّصة
يمكن أن تحتوي الخطوط أيضًا على محاور مخصصة. ويتم تحديدها ضمن ملف الخط نفسه.
على سبيل المثال، يحتوي خط 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