Giới thiệu
Ví dụ minh họa cách làm đậm (bold) chỉ một đoạn cụ thể trong chuỗi văn bản hiển thị trên TextView bằng SpannableString và StyleSpan trong Kotlin Android.
Các bước thực hiện
Bước 1: Tạo dự án mới
Android Studio > File > New Project.
Bước 2: Layout (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="70dp"
android:background="#008080"
android:padding="5dp"
android:text="TutorialsPoint"
android:textColor="#fff"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:textAlignment="center"
android:textColor="@android:color/holo_green_dark"
android:textSize="36sp" />
</RelativeLayout>
Bước 3: MainActivity.kt - SpannableString
import android.graphics.Typeface
import android.os.Bundle
import android.text.SpannableString
import android.text.Spanned
import android.text.style.StyleSpan
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
title = "KotlinApp"
val textView = findViewById(R.id.textView)
val text = "Món ăn yêu thích của tôi là Bún bò Huế"
val spannableString = SpannableString(text)
// Tạo StyleSpan BOLD
val boldSpan = StyleSpan(Typeface.BOLD)
// Áp dụng từ index 24 đến 35 (chữ "Bún bò Huế")
// Lưu ý: Index tính theo ký tự (code point), tiếng Việt có dấu vẫn là 1 char.
spannableString.setSpan(boldSpan, 24, 35, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
textView.text = spannableString
}
}
Bước 4: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.example.boldtext">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Chạy ứng dụng
Chạy app, TextView hiển thị: "Món ăn yêu thích của tôi là Bún bò Huế" (phần "Bún bò Huế" in đậm).
Các Span phổ biến khác
| Span Class | Hiệu ứng | Ví dụ |
|---|---|---|
StyleSpan(Typeface.BOLD) | In đậm | StyleSpan(Typeface.BOLD) |
StyleSpan(Typeface.ITALIC) | In nghiêng | StyleSpan(Typeface.ITALIC) |
StyleSpan(Typeface.BOLD_ITALIC) | Đậm + Nghiêng | StyleSpan(Typeface.BOLD_ITALIC) |
ForegroundColorSpan(Color.RED) | Màu chữ | ForegroundColorSpan(Color.parseColor("#FF0000")) |
BackgroundColorSpan(Color.YELLOW) | Màu nền (highlight) | BackgroundColorSpan(Color.YELLOW) |
UnderlineSpan() | Gạch chân | UnderlineSpan() |
StrikethroughSpan() | Gạch ngang | StrikethroughSpan() |
RelativeSizeSpan(1.5f) | Cỡ chữ tương đối (1.5x) | RelativeSizeSpan(1.5f) |
AbsoluteSizeSpan(24, true) | Cỡ chữ tuyệt đối (24sp) | AbsoluteSizeSpan(24, true) |
ClickableSpan | Xử lý click trên đoạn text | Xem tài liệu Android |
ImageSpan | Chèn ảnh vào text | ImageSpan(drawable) |
Kết hợp nhiều Span
val spannable = SpannableString("Chữ đỏ đậm, chữ xanh nghiêng")
val redBold = ForegroundColorSpan(Color.RED)
val blueItalic = ForegroundColorSpan(Color.BLUE)
val bold = StyleSpan(Typeface.BOLD)
val italic = StyleSpan(Typeface.ITALIC)
spannable.setSpan(redBold, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) // "Chữ "
spannable.setSpan(bold, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
spannable.setSpan(blueItalic, 6, 13, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) // "chữ xanh"
spannable.setSpan(italic, 6, 13, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
textView.text = spannable
textView.movementMethod = LinkMovementMethod.getInstance() // Cần nếu có ClickableSpan
Cách dễ dàng hơn: HTML.fromHtml (API 24+)
val htmlText = "Món ăn yêu thích là Bún bò Huế và Phở" textView.text = Html.fromHtml(htmlText, Html.FROM_HTML_MODE_LEGACY) // Hoặc dùng HtmlCompat.fromHtml(htmlText, HtmlCompat.FROM_HTML_MODE_LEGACY) từ androidx.core.text.HtmlCompat
- Hỗ trợ các thẻ:
<b>,<i>,<u>,<font color='red'>,<br/>, v.v. - Dễ đọc, dễ bảo trì hơn SpannableString thủ công.