Typeface — کلاس Android SDK از بسته android.graphics است که ظاهر فونت را نشان میدهد و برای سفارشیسازی متن در TextView و سایر کامپوننتهای UI استفاده میشود. Typeface خانواده فونت، وزن (normal, bold) و سبک (normal, italic) آن را تعیین میکند. به گفته Google Developers، Typeface از بارگذاری از فایلهای TTF، OTF، فونتهای XML و منابع سیستمی پشتیبانی میکند. این کلاس مرکزی برای مدیریت تایپوگرافی در برنامههای اندروید است.
نکات اصلی
Typeface — کلاس اندروید است که اطلاعات مربوط به فونت را کپسوله میکند: خانواده آن (Roboto, Arial, Serif) و اصلاحکنندههای سبک (ضخامت، ایتالیک). بر خلاف UIFont در iOS، Typeface حاوی اطلاعات اندازه نیست — اندازه متن به طور جداگانه از طریق ویژگی textSize در TextView یا TextStyle در Spannable تنظیم میشود. Typeface فقط مسئول ظاهر و گرانیور فونت است.
این کلاس در تمام سطوح API در دسترس است. تا Android 4.4، Typeface فقط از مجموعه محدودی از فونتهای سیستمی پشتیبانی میکرد: DEFAULT, DEFAULT_BOLD, MONOSPACE, SERIF, SANS_SERIF. از Android 8.0 (API 26) به بعد، پشتیبانی از بارگذاری فونتهای سفارشی از طریق منابع XML اضافه شد و Android 10 پشتیبانی از فونتهای متغیر را افزود.
Android چندین نمونه داخلی Typeface ارائه میدهد: Typeface.DEFAULT — فونت سیستمی Roboto (Material) یا Noto (AOSP)، DEFAULT_BOLD — نسخه ضخیم، MONOSPACE — فونت همعرض برای کد، SERIF — فونت سریف (Noto Serif)، SANS_SERIF — فونت بیسریف (Noto Sans). این ثابتها بدون زمینه در دسترس هستند و به مجوز خواندن فایل نیاز ندارند.
سیستم اندروید از Typeface برای رندر کردن تمام متنها استفاده میکند، از جمله UI سیستم، عنوانها، برچسبها و اعلانها. هر برنامه میتواند فونت پیشفرض را از طریق تم (android:fontFamily) یا برنامهنویسی از طریق setTypeface() بازنویسی کند. Typeface برای همه کامپوننتهای به ارث برده از TextView اعمال میشود: دکمهها، EditText و ویوهای سفارشی.
Android 8.0+ امکان افزودن فونت به res/font و استفاده از آنها را از طریق منابع XML فراهم میکند. فایل فونت (TTF یا OTF) در res/font قرار میگیرد و سپس مرجع R.font.font_name ایجاد میشود. Typeface از طریق ResourcesCompat.getFont(context, R.font.font_name) بارگذاری میشود. این روش ترجیح داده میشود زیرا فونت در APK کامپایل شده و از سیستمهای چیدمان ProGuard پشتیبانی میکند.
روش منبع همچنین از خانواده فونت (font family) از طریق فایل XML در res/font پشتیبانی میکند: میتوان چندین فایل برای ظاهرهای مختلف (regular, bold, italic) مشخص کرد و سیستم به طور خودکار فایل مناسب را هنگام فراخوانی setTypeface انتخاب میکند. این امر تایپوگرافی را ساده میکند — کافی است fontFamily را در تم تنظیم کنید و Android فایل مناسب را خودش انتخاب میکند.
متود Typeface.create(Typeface family, int style) نمونه فونتی با خانواده و سبک مشخص ایجاد میکند. اگر خانواده از قبل سبک درخواستی را داشته باشد، نمونه موجود برگردانده میشود. اگر سبک وجود نداشته باشد، Android آن را ترکیبی میکند — ضخامت تقلبی یا ایتالیک مصنوعی را به فونت پایه اعمال میکند.
val boldTypeface = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)
val italicTypeface = Typeface.create(Typeface.MONOSPACE, Typeface.ITALIC)
val customTypeface = ResourcesCompat.getFont(context, R.font.montserrat_regular)
textView.typeface = boldTypeface
شبه-ضخیم ترکیبی ممکن است روی فونتهای نازک بیکیفیت به نظر برسد. برای نتیجه بهتر از فایل فونت با ظاهر واقعی bold استفاده کنید. Typeface.create() با سبک ناموجود استثنا پرتاب نمیکند و نزدیکترین گزینه موجود را برمیگرداند.
برای بارگذاری Typeface از assets از Typeface.createFromAsset(assetManager, path) استفاده میشود. فونت در دایرکتوری src/main/assets/fonts/ قرار میگیرد و مسیر نسبت به assets مشخص میشود. این روش در تمام نسخههای اندروید کار میکند اما از خانواده فونتها پشتیبانی نمیکند و نیاز به مشخص کردن فایل خاص برای هر ظاهر دارد.
متود Typeface.createFromFile(File) فونت را از هر فایل دلخواه در سیستم فایل بارگذاری میکند. این برای فونتهای دانلود شده از شبکه یا کپی شده در حافظه داخلی برنامه مفید است. createFromFile همچنین به زمینه نیاز ندارد که برای وظایف پسزمینه مناسب است، اما فایل باید قابل خواندن باشد.
بارگذاری مکرر Typeface از assets از طریق createFromAsset ممکن است منجر به ایجاد اشیاء تکراری شود. هر فراخوانی createFromAsset فایل را دوباره بارگذاری میکند. توصیه میشود کش Typeface را از طریق HashMap پیادهسازی کنید که کلید آن مسیر فایل و مقدار آن نمونه بارگذاری شده است. این به ویژه برای لیستهایی با انواع مختلف فونت اهمیت دارد.
object TypefaceCache {
private val cache = mutableMapOf<String, Typeface>()
fun getTypeface(context: Context, filename: String): Typeface {
return cache.getOrPut(filename) {
Typeface.createFromAsset(context.assets, "fonts/$filename")
}
}
}
// استفاده
val typeface = TypefaceCache.getTypeface(context, "Roboto-Bold.ttf")
کش در حافظه تضمین میکند که یک فونت فقط یک بار در طول جلسه برنامه بارگذاری میشود. در تغییر پیکربندی (چرخش صفحه) کش حفظ میشود زیرا در شی companion قرار دارد. برای پاکسازی کش در صورت کمبود حافظه از WeakHashMap استفاده کنید یا به onTrimMemory گوش دهید.
Typeface از طریق متود setTypeface(Typeface tf) یا setTypeface(Typeface tf, int style) به TextView اعمال میشود. گزینه دوم امکان تغییر سبک (bold/italic) نسبت به فونت فعلی را فراهم میکند. در XML از ویژگی android:fontFamily با ارجاع به فونت یا خانواده سیستمی استفاده میشود. برای تنظیم برنامهنویسی، فراخوانی setTypeface(monospaceTypeface) فونت را به فونت مشخص شده تغییر میدهد.
Typeface بر کل متن TextView تأثیر میگذارد. اگر فونت متفاوتی در یک خط مورد نیاز باشد، از SpannableString با TypefaceSpan استفاده میشود. TypefaceSpan Typeface یا family را میپذیرد و به محدوده کاراکترها اعمال میشود. این تنها راه ترکیب فونتها در یک TextView بدون کامپوننتهای تو در تو است.
TypefaceSpan را فقط به بخشی از رشته اعمال کنید. به عنوان مثال، مقدار متغیر در متن باید با فونت همعرض نمایش داده شود و بقیه متن با فونت سیستمی. یک SpannableString ایجاد میشود و TypefaceSpan با MONOSPACE Typeface روی محدوده مورد نظر تنظیم میشود. بقیه متن با فونت اصلی TextView باقی میماند.
val text = "Code: variableName"
val spannable = SpannableString(text)
spannable.setSpan(
TypefaceSpan(Typeface.MONOSPACE),
5, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
spannable.setSpan(
ForegroundColorSpan(Color.BLUE),
5, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = spannable
متن «variableName» با فونت همعرض به رنگ آبی و کلمه «Kod:» با فونت سیستمی نمایش داده میشود. TypefaceSpan را میتوان با هر span دیگری برای کنترل دقیق روی هر بخش از متن ترکیب کرد.
Android از چندین فرمت فونت پشتیبانی میکند: TrueType (TTF), OpenType (OTF) و Web Open Font Format (WOFF2) از Android 10. TTF و OTF فرمتهای اصلی برای فونتهای سفارشی هستند. فونتهای XML (Font Family) یک فرمت جداگانه نیستند، بلکه توصیفی هستند که کدام فایل برای هر ظاهر استفاده شود.
برای استفاده از فونت سفارشی از طریق res/font یک فایل XML خانواده ایجاد کنید که مسیرهای فایلهای فونت را برای regular, bold و italic مشخص میکند. سپس در تم برنامه android:fontFamily="@font/custom_family" را تنظیم کنید. تمام TextViewهایی که از این تم استفاده میکنند به طور خودکار ظاهر صحیح را برای هر سبک دریافت میکنند.
اگر فونت از شبکه دانلود میشود، آن را در filesDir یا cacheDir ذخیره کرده و از طریق Typeface.createFromFile بارگذاری کنید. پس از بارگذاری، Typeface را در TextView بهروزرسانی کنید. برای بارگذاری ناهمگام از coroutine یا DownloadManager استفاده کنید و پس از اتمام، از طریق Handler به رشته UI ارسال کنید. این سناریوی معمولی برای برنامههایی با تایپوگرافی سفارشی بارگذاری شده در صورت نیاز است.
// ذخیره فایل فونت در حافظه داخلی
val fontFile = File(context.cacheDir, "downloaded-font.otf")
fontFile.outputStream().use { output ->
// جریان ورودی از شبکه
inputStream.copyTo(output)
}
// ایجاد Typeface از فایل
val downloadedTypeface = Typeface.createFromFile(fontFile)
textView.typeface = downloadedTypeface
قبل از بارگذاری، در دسترس بودن فایل را بررسی کنید: اگر فایل خراب یا نامعتبر باشد، Typeface.createFromFile RuntimeException پرتاب میکند. توصیه میشود فراخوانی را در try-catch قرار دهید و در صورت خطا، فونت سیستمی پیشفرض را نگه دارید.
در Jetpack Compose، Typeface Android SDK به طور مستقیم استفاده نمیشود. در عوض، Compose FontFamily و FontWeight را برای تایپوگرافی فراهم میکند. FontFamily از طریق Font.Resource و Font.File بارگذاری میشود. سیستم تایپوگرافی Compose از طریق MaterialTheme.typography تنظیم میشود، جایی که میتوان به هر سبک (h1, body1, button) یک FontFamily سفارشی اختصاص داد.
برای بارگذاری فونت از resources، Compose از Font(R.font.font_name, weight, style) استفاده میکند. فونت از assets از طریق Font(assetPath = "fonts/custom.otf", weight, style) بارگذاری میشود. پس از تعریف فونت، به Typography منتقل شده و سپس از طریق MaterialTheme.typography.bodyLarge و سبکهای مشابه اعمال میشود.
اگر Typeface آمادهای که از طریق Android SDK ایجاد شده وجود دارد، میتوان آن را در Compose از طریق TypefaceAdapter یا با ایجاد FontFamily بر اساس Typeface استفاده کرد. برای این کار Typeface را از Typeface.create دریافت کرده و به FontFamily.Custom(listOf(Font(typeface))) منتقل کنید. با این حال، توصیه میشود از رویکرد بومی با Font.Resource استفاده کنید زیرا برای Compose بهینهتر است.
بارگذاری فونتها از فایلها یک عملیات بالقوه پرهزینه است. هر فراخوانی Typeface.createFromAsset یا Typeface.createFromFile فایل را از دیسک میخواند، آن را تجزیه میکند و شی Typeface ایجاد میکند. برای فونتهای 1-2 مگابایتی، این کار 10-50 میلیثانیه در شروع سرد طول میکشد. کش کردن Typeface یک روش اجباری برای برنامههای دارای فونت سفارشی است.
Android SDK فونتهای ایجاد شده از طریق createFromAsset یا createFromFile را کش نمیکند. بر خلاف فونتهای سیستمی که در فرآیند Zygote از پیش بارگذاری میشوند، فونتهای سفارشی در هر بار مراجعه بارگذاری میشوند. توصیه میشود از LruCache یا ConcurrentHashMap با کلید شناسه فونت استفاده کنید. اندازه کش — 10-20 نمونه که مجموعه فونت معمولی برنامه را پوشش میدهد.
Android 8.0+ بارگذاری فونت را از طریق XML Font Family بهینه میکند. هنگام تعیین android:fontFamily="@font/my_family" در چیدمان XML، Android فونت را تنبل بارگذاری میکند — فقط زمانی که کامپوننت قابل مشاهده شود. سیستم همچنین فونتهای بارگذاری شده از طریق ResourcesCompat.getFont() را در کش سراسری فرآیند ذخیره میکند. این روش منبع را کارآمدترین میکند.
هنگام استفاده از Typeface در آداپترهای RecyclerView مهم است که فونت را در متود onBindViewHolder بارگذاری نکنید. بارگذاری را یک بار در زمان ایجاد آداپتر فراخوانی کنید یا از ViewHolder با Typeface از پیش بارگذاری شده استفاده کنید. اگر هر آیتم لیست به فونت منحصر به فردی نیاز دارد، کش را از طریق WeakHashMap پیادهسازی کنید و برای صرفهجویی در حافظه هنگام اسکرول به خارج از موقعیتهای قابل مشاهده آن را پاک کنید.
سوالات متداول
Typeface — یک نمونه فونت مشخص برای استفاده برنامهنویسی است. FontFamily — یک منبع XML است که گروهی از فایلهای فونت را برای ظاهرهای مختلف (regular, bold, italic) توصیف میکند. در زمان اجرا، FontFamily از طریق ResourcesCompat.getFont به Typeface تبدیل میشود. Typeface را میتوان مستقیماً از فایل و بدون FontFamily ایجاد کرد.
از Typeface.createFromFile(File) یا Typeface.DEFAULT استفاده کنید. این متودها به context نیاز ندارند زیرا با سیستم فایل یا ثابتهای داخلی کار میکنند. برای بارگذاری از assets یا منابع، context ضروری است زیرا نیاز به دسترسی به AssetManager و منابع برنامه است.
خیر، WebView از ویژگی CSS font-family برای مشخص کردن فونتها استفاده میکند. برای استفاده از فونت سفارشی در WebView، فایل فونت را در assets قرار داده و از طریق @font-face در CSS مشخص کنید. Typeface Android SDK فقط با کامپوننتهای بومی UI (TextView و وراث) کار میکند.
بله، از Android 10 (API 29). فونتهای متغیر از طریق ResourcesCompat.getFont یا Typeface.createFromFile بارگذاری میشوند. برای تنظیم محورهای تغییرپذیری (weight, width) از FontStyle در Compose یا ویژگیهای XML استفاده میشود. تغییر برنامهنویسی محور فقط از طریق API سطح پایین Skia امکانپذیر است.
شایعترین دلایل: فایل فونت در پروژه وجود ندارد، نام فایل نادرست است، فونت خراب است یا از سبک ترکیبی استفاده میشود که در فایل وجود ندارد. بررسی کنید که فایل به res/font یا assets اضافه شده باشد و در روش منبعی نام بدون پسوند ذکر شده باشد.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید