ParagraphStyle, bir metin paragrafının görsel görünümünü tanımlayan biçimlendirme parametreleri kümesidir. Mobil geliştirmede ParagraphStyle, hizalama (left, center, right, justified), satır aralığı, ilk satır girintisi, paragraflar arası boşluk ve metin yönünü içerir. Material Design Typography Guidelines (2025)'e göre, ParagraphStyle'ın uygulamanın tüm ekranlarında tutarlı kullanımı, tek tip tipografik ritim sağlar ve bölümler arasında geçiş yaparken görsel gürültüyü azaltır.
Önemli Noktalar
ParagraphStyle (paragraf stili), bir veya daha fazla metin paragrafına uygulanabilen biçimlendirme kuralları kümesidir. Tek tek karakterler düzeyinde çalışan karakter stillerinin (bold, italic, font-size) aksine, ParagraphStyle makro özellikleri yönetir: metnin kapsayıcı içinde yerleşimi, satırlar ve paragraflar arasındaki boşluklar, yazma yönü ve heceleme kuralları.
Tarihsel olarak, ParagraphStyle kavramı, her paragrafın kendi parametre kümesine sahip olduğu masaüstü yayıncılık sistemlerinden (QuarkXPress, PageMaker, InDesign) gelmektedir. Mobil geliştirmede bu yaklaşım, yazılım API'lerine dönüşmüştür: iOS'te NSMutableParagraphStyle, Android'de ParagraphStyle ve LineBreakStyle sınıfları ve Flutter'da textAlign ve textHeightBehavior gibi parametreler. Hepsi tek bir amaca hizmet eder — belirli bir metin motoruna bağlı olmadan kod aracılığıyla paragraf biçimlendirmesini yönetmek.
Bringhurst — The Elements of Typographic Style (2024)'e göre, doğru ParagraphStyle yapılandırması arayüz tipografi kültürünün temelidir. Yazı tipi ve punto metnin «sesini» tanımlarsa, paragraf stili onun «nefesini» tanımlar: ritim, duraklamalar ve vurgular. Alanın sınırlı olduğu mobil arayüzlerde, doğru ParagraphStyle, okunabilirliği kaybetmeden daha fazla bilgi sığdırmaya olanak tanır.
ParagraphStyle, her biri biçimlendirmenin belirli bir yönünden sorumlu olan birkaç özellik grubu içerir. Mobil API'lerde bulunan temel parametrelere bakalım. Hizalama, metnin yatay konumunu belirleyen ana parametredir. iOS'te NSTextAlignment, Android'de Layout.Alignment, Flutter'da TextAlign mevcuttur.
| Özellik | iOS (NSMutableParagraphStyle) | Android (Compose) | Flutter (TextStyle) |
|---|---|---|---|
| Hizalama | alignment | textAlign | textAlign |
| Sol girinti | headIndent | textIndent (Compose'da) | — |
| Sağ girinti | tailIndent | — | — |
| İlk satır girintisi | firstLineHeadIndent | textIndent (firstLine) | — |
| Paragraflar arası boşluk | paragraphSpacing | paragraphStyle (lineHeight) | — |
| Paragraftan önce boşluk | paragraphSpacingBefore | — | — |
| Metin yönü | baseWritingDirection | TextDirection (Compose) | textDirection |
| Satır sonu modu | lineBreakMode | overflow (TextStyle) | overflow (TextStyle) |
Tüm özelliklerin tüm platformlarda aynı ölçüde bulunmadığını anlamak önemlidir. Örneğin, ilk satır girintisi (firstLineHeadIndent) yalnızca iOS'te NSMutableParagraphStyle aracılığıyla tam olarak desteklenir. Android'de bu amaçla LeadingMarginSpan ile SpannableString kullanılır, Flutter'da ise özel TextSpan ve padding ile RichText kullanılır. Platformlar arası geliştirmede (Flutter, React Native), bazı ParagraphStyle özelliklerinin kapsayıcılar veya Spacer aracılığıyla öykünmesi gerekir.
iOS'te, paragraf stili ile çalışmanın ana aracı NSMutableParagraphStyle sınıfıdır — NSParagraphStyle'ın bir alt sınıfı. Paragraf biçimlendirmesini yönetmek için eksiksiz bir özellik kümesi sağlar ve NSAttributedString aracılığıyla uygulanır. NSMutableParagraphStyle yalnızca UILabel ve UITextView'de değil, aynı zamanda CTParagraphStyle aracılığıyla Core Text'te de kullanılır.
// iOS: tam ParagraphStyle yapılandırması
let paragraphStyle = NSMutableParagraphStyle()
// Hizalama
paragraphStyle.alignment = .justified // yaslanmış
// Girinti
paragraphStyle.headIndent = 16 // sol girinti
paragraphStyle.tailIndent = -16 // sağ girinti (negatif)
paragraphStyle.firstLineHeadIndent = 32 // ilk satır girintisi
// Paragraflar arası boşluk
paragraphStyle.paragraphSpacing = 12 // paragraftan sonra
paragraphStyle.paragraphSpacingBefore = 8 // paragraftan önce
// Satır yüksekliği
paragraphStyle.minimumLineHeight = 24
paragraphStyle.maximumLineHeight = 24
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 16),
.paragraphStyle: paragraphStyle
]
let label = UILabel()
label.attributedText = NSAttributedString(
string: "This paragraph has a custom ParagraphStyle.\n\nSecond paragraph with 12 pt spacing.",
attributes: attributes
)
SwiftUI'de NSMutableParagraphStyle'ın doğrudan bir karşılığı yoktur — bunun yerine bir değiştirici kombinasyonu kullanılır: hizalama için .multilineTextAlignment(), satır aralığı için .lineSpacing(). SwiftUI'de ilk satır girintisi ve paragraf boşluğu için, NSParagraphStyle'ı öznitelikler aracılığıyla destekleyen Text + padding veya AttributedString (iOS 15+'tan itibaren mevcut) kullanılmalıdır.
// SwiftUI: ParagraphStyle ile AttributedString (iOS 15+)
var attributed: AttributedString = """
This is the first paragraph with indent.
This is the second paragraph with 12 pt spacing.
"""
let ps = NSMutableParagraphStyle()
ps.paragraphSpacing = 12
ps.firstLineHeadIndent = 20
let container = AttributeContainer()
.paragraphStyle(ps)
attributed.mergeAttributes(container)
Text(attributed)
.font(.body)
Apple — Text Programming Guide (2025)'e göre, NSMutableParagraphStyle 14'e kadar farklı biçimlendirme parametresini destekler. tailIndent'ın kapsayıcı genişliğine göre negatif bir değer olarak ayarlandığını, headIndent'ın ise pozitif olduğunu hatırlamak önemlidir. Bu açık olmayan davranış, acemi iOS geliştiricilerinde sıklıkla hatalara neden olur.
Android'de ParagraphStyle'a yaklaşım, View sistemi ile Jetpack Compose arasında farklılık gösterir. Klasik View sisteminde, paragraf parametreleri TextView XML öznitelikleri (android:textAlignment, android:lineSpacingExtra) veya android.text.style paketindeki ParagraphStyle arayüzünün uygulamalarıyla SpannableString aracılığıyla ayarlanır.
// Android View sistemi: SpannableString ile ParagraphStyle
val text = "First paragraph with settings.\n\nSecond paragraph."
val spannable = SpannableString(text)
// Yaslanmış hizalama
spannable.setSpan(
AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL),
0, text.length,
Spannable.SPAN_PARAGRAPH
)
// LeadingMarginSpan ile ilk satır girintisi
spannable.setSpan(
LeadingMarginSpan.Standard(0, 20),
0, text.indexOf('\n'),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = spannable
Jetpack Compose'da ParagraphStyle, TextStyle parametreleri aracılığıyla yönetilir. Hizalama için textAlign, satır aralığı için lineHeight (sp veya em cinsinden) ve ilk satır girintisi için textIndent kullanılır. Compose ayrıca, özellikle çok dilli metin için yararlı olan, satır sonlarının ince ayarlı kontrolü için LineBreak'i (Simple, Heading, Paragraph) destekler.
// Jetpack Compose: TextStyle ile ParagraphStyle
Text(
text = "Özel stille ilk paragraf.
Girintili ikinci paragraf.",
style = TextStyle(
textAlign = TextAlign.Justify,
lineHeight = 24.sp,
textIndent = TextIndent(firstLine = 16.sp),
lineBreak = LineBreak.Paragraph
)
)
Android Developers — Compose ParagraphStyle (2025)'e göre, Compose'da TextIndent kullanırken firstLine'ı sp (dp değil) olarak ayarlamak önemlidir, çünkü ilk satır girintisi metinle birlikte ölçeklenmelidir. Girinti dp olarak ayarlanırsa, yazı tipi boyutu arttığında ilk satır girintisi görsel olarak küçülecek ve tipografik oranları bozacaktır.
Flutter'da ParagraphStyle paradigması ayrı bir sınıfa ayrılmamıştır — bunun yerine TextStyle parametreleri ve ek sınıfların bir kombinasyonu kullanılır. Hizalama TextAlign aracılığıyla, satır aralığı height (birimsiz) aracılığıyla ayarlanır ve TextHeightBehavior, ilk ve son satırın görünür girintilerini kontrol eder.
// Flutter: Text parametreleri ile ParagraphStyle
Text(
'Flutter'da stillendirilmiş paragraf.
Girintili ikinci paragraf.',
style: TextStyle(
fontSize: 16,
height: 1.5,
leadingDistribution: TextLeadingDistribution.proportional,
),
textAlign: TextAlign.justify,
textHeightBehavior: TextHeightBehavior(
applyHeightToFirstAscent: true,
applyHeightToLastDescent: true,
),
)
Daha karmaşık senaryolar için Flutter, özel TextSpan ve WidgetSpan ile RichText kullanımını sunar. Bu, tek tip biçimlendirme kurallarını koruyarak tek bir paragrafta metni satır içi widget'lar (simgeler, görüntüler) ile birleştirmeye olanak tanır. Ancak bu yaklaşım, satır sonlarının manuel kontrolünü gerektirir ve otomatik hecelemeyi desteklemez.
// Flutter: Özel paragraf biçimlendirmesiyle RichText
RichText(
text: TextSpan(
style: TextStyle(fontSize: 16, height: 1.5),
children: [
TextSpan(text: 'First paragraph with icon '),
WidgetSpan(
child: Icon(Icons.star, size: 16),
alignment: PlaceholderAlignment.middle,
),
TextSpan(text: '\n\nSecond paragraph after spacing.'),
],
),
)
Flutter Documentation — Text Widget (2025)'e göre, TextHeightBehavior, Flutter'da ParagraphStyle'ın doğru görüntülenmesi için anahtar bir parametredir. applyHeightToFirstAscent false olarak ayarlanırsa, ilk satırın üst girintisi yok sayılır ve metin kapsayıcının üst kenarına «yapışır». Bu, başlıklar için kullanışlıdır ancak ana metin için istenmeyen bir durumdur.
ParagraphStyle, her yerel ayar için yazma yönünü dikkate almalıdır. Arapça, İbranice veya Urduca (sağdan sola yazma, RTL) desteği olan mobil uygulamalarda, girinti ve hizalama yansıtılmalıdır. iOS, baseWritingDirection = .natural aracılığıyla otomatik geçişi destekler, Android TextDirection aracılığıyla, Flutter textDirection aracılığıyla.
RTL yerel ayarları için hizalama yapılandırması özel dikkat gerektirir. LTR modunda headIndent sol girintiyi ayarlarsa, RTL'de otomatik olarak sağ girinti haline gelir. Ancak, hizalama açıkça belirtildiğinde (NSTextAlignment.natural yerine NSTextAlignment.left) tüm uygulamalar bu geçişi doğru şekilde işlemez. Google Internationalization Guide (2025)'e göre, çok dilli uygulamalar için her zaman doğal hizalama kullanın ve her iki düzende de girintileri kontrol edin.
// Android: ParagraphStyle'da RTL desteği
val textView = TextView(context)
// Otomatik RTL desteğini etkinleştir
textView.textDirection = View.TEXT_DIRECTION_LOCALE
textView.textAlignment = View.TEXT_ALIGNMENT_TEXT_START
// RTL destekli Spannable
val spannable = SpannableString(arabicText)
spannable.setSpan(
AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL),
0, arabicText.length,
Spannable.SPAN_PARAGRAPH
)
Bölgesel özellikler ayrıca ilk satır girintisi için farklı kuralları da içerir. Avrupa tipografisinde, ilk satır girintisi (firstLineHeadIndent) paragraf ayırma için bir standarttır. Japon ve Çin tipografisinde de ilk satır girintisi kullanılır, ancak boyutu farklı olabilir (genellikle Avrupa geleneğinde 1,5 em'e karşılık 1 em). Arap tipografisi için ilk satır girintisi nadirdir — paragraflar daha çok dikey boşlukla ayrılır.
En yaygın hata, bireysel paragrafların farklı biçimlendirmesini dikkate almadan ParagraphStyle'ı yalnızca metin alanının genel öznitelikleri aracılığıyla kullanmaktır. ile ayrılmış birden çok paragrafa sahip bir UILabel veya TextView'de, her paragraf için farklı stillerle nitelikli metin kullanılmadığı sürece ParagraphStyle tüm metne tekdüze olarak uygulanır.
UX Collective — Common Typography Bugs in Mobile Apps (2025)'e göre, ParagraphStyle ile ilgili sorunlar mobil uygulamalardaki tüm tipografi hatalarının %18'ini oluşturur. En kritik durumlar, yanlış paragraphSpacing'in farklı satırlarda metin örtüşmesine yol açması veya RTL yerel ayarlarının LTR girintileriyle görüntülenmesidir. Her ParagraphStyle parametresi için farklı dillerde test dizeleriyle birim testleri oluşturulması önerilir.
Sıkça Sorulan Sorular
NSMutableParagraphStyle paragraf biçimlendirmesini (hizalama, girinti, satır aralığı) yönetirken, TextStyle karakter özniteliklerini (yazı tipi, renk, boyut) yönetir. Her ikisi de NSAttributedString aracılığıyla uygulanır. ParagraphStyle paragraf düzeyinde, TextStyle karakter düzeyinde çalışır. Bir paragrafta birden çok TextStyle örneği bulunabilir, ancak paragraf başına yalnızca bir ParagraphStyle bulunur.
Jetpack Compose'da ilk satır girintisi, TextStyle içindeki TextIndent aracılığıyla ayarlanır: TextStyle(textIndent = TextIndent(firstLine = 16.sp)). Değer, metinle birlikte ölçeklenmesi için sp cinsinden olmalıdır. Çok satırlı metin için girinti, yeni bir paragraf ( karakteri) başlatan her satıra uygulanır. İlk paragraf için girinti her zaman uygulanır.
SwiftUI'de paragraphSpacing'in doğrudan bir karşılığı yoktur. Paragraflar arası boşluk için, NSMutableParagraphStyle ve paragraphSpacing özelliği ile AttributedString (iOS 15+) kullanın. Veya Text("...\n\n...") aracılığıyla paragrafları ayırın ve metin blokları arasına .padding() ekleyin. Karmaşık tipografik senaryolar için UILabelRepresentable aracılığıyla NSAttributedString kullanın.
Android'de TextView'ün paragraphSpacing özelliği yoktur — LeadingMarginSpan ile SpannableString veya özel bir LineBackgroundSpan aracılığıyla ayarlanır. Satır aralığı için setLineSpacing kullanın; paragraflar arası boşluk için paragrafları ek bir ile ayırın veya birden çok TextView örneğinden oluşan bileşik bir kapsayıcı kullanın.
Doğru ParagraphStyle erişilebilirliği artırır: yeterli paragraphSpacing, bilişsel bozuklukları olan kullanıcıların paragraf sınırlarını daha iyi ayırt etmesine yardımcı olur. WCAG 2.2, paragrafların görsel olarak ayrılmasını (girinti veya boşluk) önerir. ParagraphSpacing, 1,5 × line-height değerinden az olmamalıdır. RTL yerel ayarları için girintinin doğru yansıtıldığını doğrulayın.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun