Teman-teman, semua bagus Jumat. Kami ingin membagikan terjemahan artikel yang disiapkan khusus untuk siswa kursus
“Pengembang Android. Kursus Lanjutan .
" Selamat membaca.

Cara mendeklarasikan teks secara gaya di Android.
Virginia Poltrack IllustrationTextView
dalam aplikasi Android menyediakan beberapa atribut untuk menata teks dan berbagai cara untuk menerapkannya. Atribut ini dapat diatur secara langsung di tata letak, menerapkan gaya ke tampilan atau tema ke tata letak, atau, jika Anda mau, mengatur tampilan teks. Tapi apa yang harus digunakan? Dan apa yang terjadi jika Anda menggabungkannya?
Apa dan kapan menggunakannya?Artikel ini menjelaskan berbagai pendekatan untuk stylization teks deklaratif (yaitu, ketika Anda menentukan gaya dalam file XML), membahas ruang lingkup dan prioritas masing-masing metode.
tl; dr;
Anda
harus membaca seluruh posting, tetapi di sini adalah ringkasannya.
Ingat urutan prioritas berbagai metode penataan - jika Anda mencoba menstilisasi beberapa teks dan tidak melihat hasil yang diharapkan, maka kemungkinan besar perubahan Anda akan ditimpa oleh sesuatu dengan prioritas lebih tinggi dalam hierarki ini:
Hirarki metode penataan teksSaya akan menyarankan prosedur penataan berikut:
- Setel gaya aplikasi apa pun di
textViewStyle
sebagai gaya default untuk tema Anda. - Pasang set (kecil)
TextAppearance
yang akan digunakan aplikasi Anda (atau gunakan / wariskan dari gaya MaterialComponent), dan rujuk langsung dari pandangan Anda - Buat
style
dengan mengatur atribut yang tidak didukung oleh TextAppearance
(yang dengan sendirinya akan menentukan salah satu dari TextAppearance
Anda). - Lakukan gaya unik apa pun secara langsung di tata letak.
Tunjukkan beberapa gaya
Anda bisa langsung mengatur atribut
TextView
di tata letak, tetapi pendekatan ini bisa lebih membosankan dan tidak aman. Bayangkan dengan cara ini Anda mencoba memperbarui warna semua TextViews dalam aplikasi. Seperti semua tampilan lainnya, Anda dapat (dan seharusnya!) Menggunakan gaya untuk memastikan konsistensi, penggunaan kembali, dan kemudahan memperbarui. Untuk tujuan ini, saya sarankan membuat gaya untuk teks kapan pun Anda mungkin ingin menerapkan gaya yang sama ke beberapa tampilan. Ini sangat sederhana dan sebagian besar didukung oleh sistem tampilan Android.
Apa yang terjadi di bawah tenda saat Anda mengatur tampilan? Jika Anda pernah menulis tampilan kustom Anda, Anda mungkin melihat panggilan ke
konteks.obtainStyledAttributes (AttributeSet, int [], int, int) . Dengan demikian, sistem tampilan di Android beralih ke tampilan atribut yang ditentukan dalam tata letak. Parameter
AttributeSet
, pada kenyataannya, dapat dianggap sebagai peta parameter XML yang Anda tentukan dalam tata letak Anda. Jika AttributeSet menetapkan gaya,
gaya dibaca pertama kali , dan kemudian atribut yang ditentukan secara langsung dalam tampilan diterapkan padanya. Jadi, kita sampai pada aturan prioritas pertama.
Lihat → GayaAtribut yang didefinisikan secara langsung dalam tampilan selalu "menang" dan mengesampingkan atribut yang didefinisikan dalam gaya. Perhatikan bahwa
kombinasi atribut style dan view diterapkan; mendefinisikan atribut dalam tampilan, yang juga ditentukan dalam gaya,
tidak membatalkan seluruh gaya. Perlu juga dicatat bahwa dalam pandangan Anda tidak ada cara nyata untuk menentukan dari mana stilisasi berasal; Ini ditentukan oleh sistem tampilan untuk Anda sekali dalam panggilan yang sama. Anda tidak bisa mendapatkan kedua opsi dan memilih.
Meskipun gaya sangat berguna, mereka memiliki keterbatasan. Salah satunya adalah bahwa Anda hanya dapat menerapkan satu gaya ke tampilan (berbeda dengan sesuatu seperti CSS, di mana Anda dapat menerapkan beberapa kelas).
TextView
, bagaimanapun, memiliki trik, ia menyediakan atribut
TextAppearance
, yang bekerja mirip dengan
style
. Jika Anda
TextAppearance
teks melalui
TextAppearance
, biarkan atribut
style
gratis untuk gaya lain, yang terlihat praktis. Mari kita lihat lebih dekat apa itu
TextAppearance
dan bagaimana cara kerjanya.
Penampilan teks
Tidak ada yang ajaib di
TextAppearance
(misalnya, mode rahasia untuk menerapkan beberapa gaya yang seharusnya tidak Anda ketahui !!!!),
TextView
menyelamatkan Anda dari pekerjaan yang tidak perlu. Mari kita lihat pada konstruktor
TextView
untuk memahami apa yang terjadi.
TypedArray a = theme.obtainStyledAttributes(attrs, com.android.internal.R.styleable.TextViewAppearance, defStyleAttr, defStyleRes); TypedArray appearance = null; int ap = a.getResourceId(com.android.internal.R.styleable.TextViewAppearance_textAppearance, -1); a.recycle(); if (ap != -1) { appearance = theme.obtainStyledAttributes(ap, com.android.internal.R.styleable.TextAppearance); } if (appearance != null) { readTextAppearance(context, appearance, attributes, false); appearance.recycle(); }
Jadi apa yang terjadi di sini? Pada dasarnya,
TextView
pertama terlihat untuk melihat apakah Anda menentukan
android:textAppearance
, jika demikian, itu memuat gaya ini dan menerapkan semua properti yang terdaftar di sana. Kemudian, ia memuat semua atribut dari tampilan (yang ia ingat, termasuk gaya) dan menerapkannya. Jadi kita sampai pada aturan prioritas kedua:
Lihat → Gaya → Tampilan TeksKarena penampilan teks diperiksa terlebih dahulu, atribut apa pun yang didefinisikan secara langsung dalam tampilan atau gaya akan menimpanya.
Dengan
TextAppearance
, ada
TextAppearance
lain yang perlu diingat: mendukung
subset atribut gaya yang ditawarkan
TextView
. Untuk lebih memahami apa yang saya maksud, mari kembali ke baris ini:
obtainStyledAttributes(ap, android.R.styleable.TextAppearance);
Kami melihat versi
receiveStyledAttributes
dengan 4 argumen, versi 2-argumen ini sedikit berbeda dari itu. Dia melihat style yang diberikan (seperti yang didefinisikan oleh
id
parameter pertama) dan memfilternya hanya sesuai dengan atribut dalam style yang muncul pada parameter kedua, array
attrs
. Android.R.styleable.TextAppearance yang sangat bergaya mendefinisikan ruang lingkup
TextAppearance
. Melihat definisi ini, kita melihat bahwa
TextAppearance
mendukung banyak,
tetapi tidak semua, atribut yang
didukung TextView
.
<attr name="textColor" /> <attr name="textSize" /> <attr name="textStyle" /> <attr name="typeface" /> <attr name="fontFamily" /> <attr name="textColorHighlight" /> <attr name="textColorHint" /> <attr name="textColorLink" /> <attr name="textAllCaps" format="boolean" /> <attr name="shadowColor" format="color" /> <attr name="shadowDx" format="float" /> <attr name="shadowDy" format="float" /> <attr name="shadowRadius" format="float" /> <attr name="elegantTextHeight" format="boolean" /> <attr name="letterSpacing" format="float" /> <attr name="fontFeatureSettings" format="string" />
Atribut Styling Didukung oleh TextAppearance
Berikut adalah beberapa atribut
TextView
yang tidak termasuk dalam
TextAppearance
:
lineHeight[Multiplier|Extra]
,
lines
,
breakStrategy
dan
hyphenationFrequency
.
TextAppearance
berfungsi pada level karakter, bukan level paragraf, sehingga atribut yang memengaruhi seluruh tata letak tidak didukung.
Oleh karena itu,
TextAppearance
sangat berguna, memungkinkan kita untuk mendefinisikan gaya yang berorientasi pada atribut gaya teks, dan membiarkan
style
dalam tampilan gratis untuk keperluan lain. Namun, ini memiliki cakupan terbatas dan berada di bagian bawah rantai prioritas, jadi jangan lupa tentang batasannya.
Default yang wajar
Ketika kami melihat bagaimana tampilan Android menyelesaikan atribut (
context.obtainStyledAttributes
), kami sebenarnya menyederhanakannya sedikit. Dia memanggil
theme.obtainStyledAttributes (menggunakan
Theme Context
saat ini 'a). Saat memeriksa
tautan , urutan prioritas yang kami teliti sebelumnya ditampilkan, dan 2 tempat lagi diindikasikan untuk mencari penyelesaian atribut: gaya default untuk tampilan dan tema.
Saat menentukan nilai akhir atribut tertentu, empat parameter input ikut bermain:
- Nilai atribut apa pun di AtributSet ini.
- Sumber daya style yang ditentukan dalam AttributeSet (bernama "style").
- Gaya default ditentukan oleh defStyleAttr dan defstyleres
- Nilai dasar di utas ini.
Urutan Prioritas Styling dari Dokumentasi TemaKami akan kembali ke tema, tapi mari kita lihat gaya default terlebih dahulu. Apa gaya default ini? Untuk menjawab pertanyaan ini, saya pikir akan berguna untuk mengambil jalan keluar kecil dari tema
TextView
dan melihat
Button
sederhana. Ketika Anda memasukkan
<
Button
>
ke tata letak Anda, tampilannya seperti ini.
Tombol standarMengapa Jika Anda melihat kode sumber
Button
, Anda akan melihat bahwa kode itu agak sedikit:
public class Button extends TextView { public Button(Context context) { this(context, null); } public Button(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.buttonStyle); } public Button(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public CharSequence getAccessibilityClassName() { return Button.class.getName(); } @Override public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) { if (getPointerIcon() == null && isClickable() && isEnabled()) { return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND); } return super.onResolvePointerIcon(event, pointerIndex); } }
Itu saja! Inilah seluruh kelas (tidak ada komentar). Anda bisa memeriksanya sendiri di
sini . Saya akan menunggu Jadi dari mana latar belakang, huruf kapital, riak, dll. Berasal? Anda mungkin telah terjawab, tetapi semuanya akan didefinisikan dalam konstruktor dengan 2 argumen; yang dipanggil saat tata letak diambil dari XML. Ini adalah parameter terakhir yang mendefinisikan
defaultStyleAttr
di
com.android.internal.R.attr.buttonStyle
. Ini adalah gaya default, yang pada dasarnya adalah titik referensi tidak langsung, memungkinkan Anda menentukan gaya default. Itu tidak menunjuk langsung ke gaya, tetapi memungkinkan Anda untuk menunjuk ke salah satu yang ditentukan dalam topik Anda yang akan memeriksa ketika menyelesaikan atribut. Dan itulah yang biasanya dilakukan oleh semua tema yang Anda warisi untuk memberikan tampilan dan nuansa widget standar. Misalnya, jika Anda melihat topik Materi, ia mendefinisikan
@style/Widget.Material.Light.Button
, dan gaya inilah yang menyediakan semua atribut yang
theme.obtainStyledAttributes
akan
theme.obtainStyledAttributes
jika Anda tidak menentukan hal lain.
Kembali ke
TextView
, ini juga menawarkan gaya default:
textViewStyle
. Ini bisa sangat nyaman jika Anda ingin menerapkan beberapa gaya ke setiap TextView di aplikasi Anda. Misalkan Anda ingin mengatur jarak garis default ke 1.2. Anda dapat melakukan ini dengan
style/TextAppearance
dan mencoba menerapkannya selama peninjauan kode (atau mungkin bahkan dengan aturan kustom yang elegan di Lint), tetapi Anda harus waspada dan memastikan bahwa Anda merekrut anggota tim baru , hati-hati dengan refactoring, dll.
Pendekatan yang lebih baik adalah menentukan gaya default Anda sendiri untuk semua
TextView
dalam aplikasi, mengatur perilaku yang diinginkan. Anda dapat melakukan ini dengan mengatur gaya Anda sendiri untuk
textViewStyle
, yang diwarisi dari platform atau dari
MaterialComponents/AppCompat
secara default.
<style name="Theme.MyApp" parent="@style/Theme.MaterialComponents.Light"> ... <item name="android:textViewStyle">@style/Widget.MyApp.TextView</item></style> <style name="Widget.MyApp.TextView" parent="@android:style/Widget.Material.TextView"> <item name="android:textAppearance">@style/TextAppearance.MyApp.Body</item> <item name="android:lineSpacingMultiplier">@dimen/text_line_spacing</item> </style>
Dengan mengingat hal ini, aturan prioritas kami berupa:
Lihat -> Gaya -> Gaya Default -> TextAppearanceSebagai bagian dari resolusi atribut sistem tampilan, slot ini diisi setelah gaya (sehingga segala sesuatu dalam gaya dibatalkan oleh gaya yang diterapkan atau melihat atribut secara default), tetapi masih akan menimpa tampilan teks. Gaya default bisa sangat nyaman. Jika Anda pernah memutuskan untuk menulis tampilan kustom Anda sendiri, mereka bisa menjadi cara yang ampuh untuk menerapkan perilaku default, membuatnya mudah untuk dikustomisasi.
Jika Anda mewarisi widget dan tidak menentukan gaya default Anda sendiri, maka pastikan untuk menggunakan gaya kelas induk default di konstruktor (jangan hanya lulus 0). Misalnya, jika Anda mewarisi dari
AppCompatTextView
dan menulis konstruktor Anda sendiri dengan 2 argumen, pastikan untuk melewati
android.R.attr.textViewStyle defaultStyleAttr
(
seperti di sini ), jika tidak, Anda akan kehilangan perilaku kelas induk.
Tema
Seperti disebutkan sebelumnya, ada cara lain (terakhir, saya berjanji) untuk memberikan informasi gaya.
theme.obtainStyledAttributes
tempat
theme.obtainStyledAttributes
akan melihat langsung ke topik itu sendiri. Artinya, jika Anda menambahkan atribut gaya ke tema Anda, misalnya
android:textColor
, sistem tampilan akan memilihnya sebagai pilihan terakhir. Sebagai aturan, itu adalah ide yang buruk untuk mencampur atribut tema dan atribut gaya, yaitu, apa yang Anda terapkan langsung ke tampilan, sebagai aturan, tidak boleh ditetapkan untuk tema (dan sebaliknya), tetapi ada beberapa pengecualian langka.
Salah satu contohnya adalah ketika Anda mencoba mengubah font di seluruh aplikasi. Anda dapat menggunakan salah satu metode yang dijelaskan di atas, tetapi menyesuaikan secara manual gaya / tampilan teks di mana-mana akan menjadi monoton dan tidak aman, dan gaya default hanya akan bekerja di tingkat widget; subkelas dapat mengesampingkan perilaku ini, misalnya tombol menentukan
android:buttonStyle
mereka sendiri
android:buttonStyle
, yang
android:textViewStyle
Anda
android:textViewStyle
tidak akan mengambil. Sebagai gantinya, Anda dapat menentukan font di tema Anda:
<style name="Theme.MyApp" parent="@style/Theme.MaterialComponents.Light"> ... <item name="android:fontFamily">@font/space_mono</item> </style>
Sekarang setiap tampilan yang mendukung atribut ini akan mengambilnya jika tidak diganti oleh sesuatu dengan prioritas lebih tinggi:
Lihat → Gaya → Gaya Default → Tema → TextAppearanceSekali lagi, karena ini adalah bagian dari sistem penataan tampilan, itu akan menimpa semua yang disediakan dalam bentuk teks, tetapi akan ditimpa oleh atribut yang lebih spesifik.
Ingat prioritas ini. Dalam contoh kami dengan font untuk seluruh aplikasi, Anda dapat mengharapkan
Toolbar
mengambil font ini, karena mengandung judul, yang merupakan
TextView
. Kelas Toolbar itu sendiri, bagaimanapun, mendefinisikan gaya default yang mengandung
titleTextAppearance
, yang mendefinisikan
android:fontFamily
, dan menetapkannya langsung di header
TextView
, menimpa nilai level tema. Gaya tingkat topik bisa berguna, tetapi mudah ditimpa, jadi pastikan itu diterapkan dengan benar.
Bonus: Masalah yang Tidak Terselesaikan
Seluruh artikel ini dikhususkan untuk desain teks deklaratif di tingkat tampilan, yaitu, bagaimana gaya seluruh
TextView
selama mengisi. Gaya apa pun yang diterapkan setelah mengisi (misalnya,
textView.setTextColor(…)
) akan menggantikan gaya deklaratif.
TextView
juga mendukung gaya yang lebih kecil melalui
Span
. Saya tidak akan membahas topik ini, karena dijelaskan secara rinci dalam artikel oleh
Florina Muntenescu .
→
Spantastic text styling dengan Spans→
Rentang underspandingSaya akan menyebutkan ini untuk kelengkapan, untuk diingat bahwa gaya dan rentang program akan berada di urutan teratas prioritas:
Rentang → Setter → Tampilan → Gaya → Gaya Default → Tema → TextAppearancePilih gaya Anda
Meskipun ada beberapa cara untuk menata teks Anda, memahami perbedaan antara metode dan keterbatasannya membantu Anda menemukan alat yang tepat untuk tugas tertentu atau memahami mengapa satu metode lebih diutamakan daripada yang lain.
Memiliki gaya teks yang bagus!
Kami mengundang semua orang ke
webinar gratis dalam kerangka yang akan kami kenali dengan kerangka DI Dagger 2: kami akan mempelajari bagaimana Dagger2 menghasilkan kode, kami akan berurusan dengan penjelasan JSR 330 dan konstruksi Dagger2, kami akan belajar cara menggunakan Dagger2 dalam aplikasi multi-modul dan mempertimbangkan Dagger Android Injector.